@allior/wmake-cli 0.0.6 → 0.0.7

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/widget.js CHANGED
@@ -1,182 +1,138 @@
1
- /**
2
- * Сборка виджета: html.txt, js.txt, css.txt, fields.txt, data.txt и архив .zip.
3
- * Все пути относительно текущей папки (откуда вызывается скрипт).
4
- */
5
1
  import fs from "node:fs";
6
2
  import path from "node:path";
7
- import { spawnSync } from "node:child_process";
8
- import { runGenerateFields, runGenerateFieldsFromModule, } from "./generate-fields.js";
9
- /** Текущая папка (каталог проекта виджета). */
10
- function getProjectDir() {
11
- return path.resolve(process.cwd());
12
- }
13
- function run(cmd, args, cwd, env) {
14
- const r = spawnSync(cmd, args, {
15
- cwd,
16
- stdio: "inherit",
17
- shell: true,
18
- env: { ...process.env, ...env },
3
+ import { build } from "vite";
4
+ import { getRawWmakeGlobals, getWmakeDeps, getWmakeDepsWithVersions } from "./vite-config.js";
5
+ import { generateMergedFields } from "./generate-fields.js";
6
+ import admZip from "adm-zip";
7
+ /** Builds project for StreamElements widget using CDN mode */
8
+ export async function buildWidget(options = {}) {
9
+ const { full = false, seDir } = options;
10
+ const projectDir = process.cwd();
11
+ await build({
12
+ configFile: path.resolve(projectDir, "vite.widget.config.ts"),
13
+ build: {
14
+ emptyOutDir: true,
15
+ minify: true,
16
+ }
19
17
  });
20
- return r.status === 0;
21
- }
22
- function getPackageManager() {
23
- const userAgent = process.env.npm_config_user_agent || "";
24
- if (userAgent.includes("bun"))
25
- return "bun";
26
- if (userAgent.includes("pnpm"))
27
- return "pnpm";
28
- if (userAgent.includes("yarn"))
29
- return "yarn";
30
- return "npm";
31
- }
32
- export async function buildWidget(options) {
33
- const projectDir = getProjectDir();
34
18
  const distDir = path.join(projectDir, "dist");
35
- const buildDir = path.resolve(projectDir, process.env.BUILD_DIR ?? "build");
36
- const archiveName = process.env.ARCHIVE_NAME ?? "widget";
37
- console.log("Generating fields...");
38
- const basePath = path.join(projectDir, "fields.base.json");
39
- const fieldsTsPath = path.join(projectDir, "fields.ts");
40
- if (fs.existsSync(basePath)) {
41
- const mod = (await import("@allior/wmake-streamelements-events"));
42
- runGenerateFields({
43
- fieldsDir: projectDir,
44
- testMessages: mod.testMessages,
45
- testAlerts: mod.testAlerts,
46
- });
47
- }
48
- else if (fs.existsSync(fieldsTsPath)) {
49
- runGenerateFieldsFromModule(fieldsTsPath);
50
- }
51
- else {
52
- console.log("No fields.base.json or fields.ts found, skipping fields generation");
53
- }
54
- console.log("Building...");
55
- const buildEnv = options.full ? { BUILD_FULL: "1" } : {};
56
- if (!run(getPackageManager(), ["run", "build"], projectDir, buildEnv)) {
57
- throw new Error("Build failed.");
58
- }
59
- if (!fs.existsSync(distDir)) {
60
- throw new Error("dist not found. Run build first.");
61
- }
62
- fs.mkdirSync(buildDir, { recursive: true });
63
- const html = fs.readFileSync(path.join(distDir, "index.html"), "utf-8");
64
- fs.writeFileSync(path.join(buildDir, "html.txt"), html);
65
- const assetsDir = path.join(distDir, "assets");
66
- const findFiles = (dir, ext) => {
67
- const found = [];
68
- const walk = (d) => {
69
- if (!fs.existsSync(d))
70
- return;
71
- for (const e of fs.readdirSync(d)) {
72
- const full = path.join(d, e);
73
- const stat = fs.statSync(full);
74
- if (stat.isDirectory())
75
- walk(full);
76
- else if (e.endsWith(ext))
77
- found.push(full);
78
- }
79
- };
80
- walk(dir);
81
- return found;
82
- };
83
- const jsFiles = findFiles(assetsDir, ".js");
84
- const cssFiles = findFiles(assetsDir, ".css");
85
- if (jsFiles.length === 0 || cssFiles.length === 0) {
86
- throw new Error("Expected .js and .css in dist/assets");
87
- }
88
- let finalJs = fs.readFileSync(jsFiles[0], "utf-8");
89
- // Если мы НЕ в FULL режиме, оборачиваем в проверку готовности глобалов
90
- if (!options.full) {
91
- const { getRawWmakeGlobals } = await import("./vite-config.js");
19
+ const buildDir = path.join(projectDir, "build");
20
+ if (!fs.existsSync(buildDir))
21
+ fs.mkdirSync(buildDir, { recursive: true });
22
+ let html = fs.readFileSync(path.join(distDir, "index.html"), "utf-8");
23
+ let css = fs.readFileSync(path.join(distDir, "assets/style.css"), "utf-8");
24
+ let js = fs.readFileSync(path.join(distDir, "assets/index.js"), "utf-8");
25
+ if (!full) {
92
26
  const rawGlobals = getRawWmakeGlobals(projectDir);
93
27
  const requiredGlobals = JSON.stringify(Array.from(new Set(Object.values(rawGlobals))));
94
- finalJs = `(function() {
95
- var req = ${requiredGlobals};
96
- function check() {
97
- var missing = [];
98
- for (var i = 0; i < req.length; i++) {
99
- if (!window[req[i]]) { missing.push(req[i]); }
100
- }
101
- if (missing.length === 0) {
102
- console.log("[WMAKE] All dependencies confirmed: " + req.join(", "));
103
- var run = function() {
104
- // Принудительно гарантируем наличие переменных в глобальной области
105
- ${Array.from(new Set(Object.values(rawGlobals))).map(g => `if (!window.${g}) window.${g} = undefined; var ${g} = window.${g};`).join(" ")}
106
- try {
107
- ${finalJs}
108
- } catch (e) {
109
- console.error("[WMAKE] Runtime error during widget execution:", e);
110
- }
111
- };
112
- run();
113
- } else {
114
- if (window.__WMAKE_LOG_MISSING !== missing.join(",")) {
115
- console.warn("[WMAKE] Waiting for dependencies: " + missing.join(", "));
116
- window.__WMAKE_LOG_MISSING = missing.join(",");
117
- }
118
- setTimeout(check, 100);
119
- }
120
- }
121
- console.log("[WMAKE] Initializing dependency check...");
122
- check();
123
- })();`;
28
+ const wmakeDepsWithVersions = getWmakeDepsWithVersions(projectDir);
29
+ const wmakeDeps = getWmakeDeps(projectDir);
30
+ const globalsInOrder = Array.from(new Set(Object.values(rawGlobals)));
31
+ const loaderJs = `(function() {
32
+ var req = ${requiredGlobals};
33
+ var wmakeDeps = ${JSON.stringify(wmakeDeps)};
34
+ var wmakeFallbacks = ${JSON.stringify(wmakeDepsWithVersions)};
35
+
36
+ for (var i = 0; i < req.length; i++) {
37
+ if (!window.hasOwnProperty(req[i])) window[req[i]] = undefined;
38
+ }
39
+
40
+ function check() {
41
+ var missing = [];
42
+ for (var i = 0; i < req.length; i++) {
43
+ if (!window[req[i]]) { missing.push(req[i]); }
124
44
  }
125
- fs.writeFileSync(path.join(buildDir, "js.txt"), finalJs);
126
- fs.writeFileSync(path.join(buildDir, "css.txt"), fs.readFileSync(cssFiles[0], "utf-8"));
127
- const fieldsJsonPath = path.join(projectDir, "fields.json");
128
- if (fs.existsSync(fieldsJsonPath)) {
129
- fs.copyFileSync(fieldsJsonPath, path.join(buildDir, "fields.txt"));
45
+ if (missing.length === 0) {
46
+ console.log("[WMAKE] All context dependencies initialized");
47
+ var run = function() {
48
+ ${globalsInOrder.map(g => `var ${g} = window.${g};`).join(" ")}
49
+ try {
50
+ ${js.trim()}
51
+ } catch (e) {
52
+ console.error("[WMAKE] Runtime error:", e);
53
+ }
54
+ };
55
+ run();
56
+ } else {
57
+ setTimeout(check, 100);
130
58
  }
131
- const pkgPath = path.join(projectDir, "package.json");
132
- const wmakeVersion = fs.existsSync(pkgPath) &&
133
- (() => {
134
- try {
135
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
136
- return typeof pkg.version === "string" ? pkg.version : undefined;
137
- }
138
- catch {
139
- return undefined;
140
- }
141
- })();
142
- const dataPath = path.join(projectDir, "data.json");
143
- const data = fs.existsSync(dataPath)
144
- ? JSON.parse(fs.readFileSync(dataPath, "utf-8"))
145
- : {};
146
- if (wmakeVersion) {
147
- data.wmakeVersion = wmakeVersion;
59
+ }
60
+
61
+ function injectScripts(fieldData) {
62
+ var CDN_BASE = "https://cdn.jsdelivr.net/npm";
63
+ var head = document.getElementsByTagName("head")[0];
64
+
65
+ var queue = [];
66
+ for (var i = 0; i < wmakeDeps.length; i++) {
67
+ queue.push({ pkg: wmakeDeps[i], entry: "root" });
68
+ queue.push({ pkg: wmakeDeps[i], entry: "react" });
148
69
  }
149
- fs.writeFileSync(path.join(buildDir, "data.txt"), JSON.stringify(data, null, 2));
150
- console.log("Widget files:", path.join(buildDir, "html.txt"), "js.txt, css.txt, fields.txt, data.txt");
151
- const zipPath = path.join(distDir, `${archiveName}.zip`);
152
- const zip = spawnSync("zip", ["-r", zipPath, "."], {
153
- cwd: buildDir,
154
- stdio: "pipe",
155
- });
156
- if (zip.status === 0) {
157
- console.log("Archive:", zipPath);
70
+
71
+ function loadNext(qIdx) {
72
+ if (qIdx >= queue.length) {
73
+ check();
158
74
  return;
75
+ }
76
+
77
+ var item = queue[qIdx];
78
+ var pkg = item.pkg;
79
+ var name = pkg.replace("@allior/wmake-", "");
80
+ var pascalName = name.split("-").map(function(w) { return w.charAt(0).toUpperCase() + w.slice(1); }).join("");
81
+ var fieldKey = "wmake" + pascalName + "Version";
82
+ var version = (fieldData && fieldData[fieldKey]) || wmakeFallbacks[pkg] || "latest";
83
+
84
+ var src = CDN_BASE + "/" + pkg + "@" + version + "/dist/" + item.entry + "/index.iife.js";
85
+ var script = document.createElement("script");
86
+ script.src = src;
87
+ script.onload = function() { loadNext(qIdx + 1); };
88
+ script.onerror = function() { loadNext(qIdx + 1); };
89
+ head.appendChild(script);
159
90
  }
160
- try {
161
- const AdmZip = (await import("adm-zip")).default;
162
- const archive = new AdmZip();
163
- for (const f of [
164
- "html.txt",
165
- "js.txt",
166
- "css.txt",
167
- "fields.txt",
168
- "data.txt",
169
- ]) {
170
- const fp = path.join(buildDir, f);
171
- if (fs.existsSync(fp))
172
- archive.addLocalFile(fp, "", f);
173
- }
174
- archive.writeZip(zipPath);
175
- console.log("Archive (adm-zip):", zipPath);
91
+
92
+ loadNext(0);
93
+ }
94
+
95
+ window.addEventListener("onWidgetLoad", function(obj) {
96
+ var detail = obj.detail;
97
+ window.__WMAKE_INIT_DATA__ = detail;
98
+ injectScripts(detail && detail.fieldData);
99
+ });
100
+ })();`;
101
+ js = loaderJs;
176
102
  }
177
- catch (e) {
178
- console.error("zip failed and adm-zip fallback error:", e);
179
- console.error("Install 'zip' (e.g. apk add zip) or ensure adm-zip is installed.");
180
- throw e;
103
+ fs.writeFileSync(path.join(buildDir, "html.txt"), html, "utf-8");
104
+ fs.writeFileSync(path.join(buildDir, "css.txt"), css, "utf-8");
105
+ fs.writeFileSync(path.join(buildDir, "js.txt"), js, "utf-8");
106
+ const fields = generateMergedFields(projectDir, seDir, {
107
+ skipWmakeVersions: options.skipWmakeVersions,
108
+ skipTestAlerts: options.skipTestAlerts,
109
+ skipTestMessages: options.skipTestMessages,
110
+ });
111
+ fs.writeFileSync(path.join(buildDir, "fields.txt"), JSON.stringify(fields, null, 2), "utf-8");
112
+ const dataPath = seDir
113
+ ? path.join(projectDir, seDir, "data.json")
114
+ : path.join(projectDir, "data.json");
115
+ let dataFilename = "";
116
+ if (fs.existsSync(dataPath)) {
117
+ dataFilename = "data.txt";
118
+ fs.writeFileSync(path.join(buildDir, dataFilename), fs.readFileSync(dataPath, "utf-8"), "utf-8");
181
119
  }
120
+ const iniContent = `[HTML]
121
+ path = "html.txt"
122
+
123
+ [CSS]
124
+ path = "css.txt"
125
+
126
+ [JS]
127
+ path = "js.txt"
128
+
129
+ [FIELDS]
130
+ path = "fields.txt"
131
+ ${dataFilename ? `\n[DATA]\npath = "${dataFilename}"` : ""}
132
+ `;
133
+ fs.writeFileSync(path.join(buildDir, "widget.ini"), iniContent, "utf-8");
134
+ const zip = new admZip();
135
+ zip.addLocalFolder(buildDir);
136
+ const zipPath = path.join(distDir, "widget.zip");
137
+ zip.writeZip(zipPath);
182
138
  }
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@allior/wmake-cli",
3
- "version": "0.0.6",
4
- "description": "Streamiby/wmake CLI: build widgets, base64 encode assets, generate fields",
3
+ "version": "0.0.7",
4
+ "description": "WMake CLI: build widgets, base64 encode assets, generate fields",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
8
8
  ".": "./dist/index.js",
9
- "./vite-config": "./dist/vite-config.js",
10
- "./vite-plugin": "./dist/vite-config.js"
9
+ "./vite": "./dist/vite-config.js"
11
10
  },
12
11
  "bin": {
13
12
  "wmake-cli": "dist/bin.js",
package/src/bin.ts CHANGED
@@ -1,82 +1,44 @@
1
- #!/usr/bin/env node
2
- import path from "node:path";
3
- import fs from "node:fs";
1
+ #!/usr/bin/env bun
4
2
  import { Command } from "commander";
5
- import { processPath } from "./base64.js";
6
3
  import { buildWidget } from "./widget.js";
7
4
  import { runGenerateFields } from "./generate-fields.js";
8
- import { runExtractTestData } from "./extract-test-data.js";
5
+ import { readFileSync } from "node:fs";
6
+ import { fileURLToPath } from "node:url";
7
+ import path from "node:path";
8
+
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ const pkg = JSON.parse(readFileSync(path.join(__dirname, "../package.json"), "utf8"));
9
11
 
10
12
  const program = new Command();
11
13
 
12
- program.name("wmake").description("CLI for streamiby / wmake").version("1.0.0");
14
+ program
15
+ .name("wmake")
16
+ .description("Build tool for @allior/wmake components")
17
+ .version(pkg.version);
13
18
 
14
19
  program
15
20
  .command("widget")
16
- .description("Build chat-demo into widget files and zip in examples/chat-demo/dist")
17
- .option("--full", "Full bundle (no CDN external), like the old build")
18
- .action(async (opts: { full?: boolean }) => {
19
- try {
20
- await buildWidget({ full: opts.full });
21
- } catch (e) {
22
- console.error((e as Error).message);
23
- process.exit(1);
24
- }
21
+ .description("Build a StreamElements widget")
22
+ .option("-f, --full", "Build a full bundle without CDN deps")
23
+ .option("-s, --se-dir <dir>", "Directory containing StreamElements files (fields.json, data.json)")
24
+ .option("--no-wmake-versions", "Do not include wmake versions in fields")
25
+ .option("--no-test-alerts", "Do not include test alerts in fields")
26
+ .option("--no-test-messages", "Do not include test messages in fields")
27
+ .action(async (options) => {
28
+ await buildWidget({
29
+ full: options.full,
30
+ seDir: options.seDir,
31
+ skipWmakeVersions: !options.wmakeVersions,
32
+ skipTestAlerts: !options.testAlerts,
33
+ skipTestMessages: !options.testMessages
34
+ });
25
35
  });
26
36
 
27
37
  program
28
38
  .command("generate-fields")
29
- .description("Generate fields.json from fields.base.json and test data objects (WMAKE_FIELDS_DIR)")
30
- .action(async () => {
31
- try {
32
- const fieldsDir = process.env.WMAKE_FIELDS_DIR;
33
- if (!fieldsDir?.trim()) {
34
- throw new Error("WMAKE_FIELDS_DIR must be set.");
35
- }
36
- const mod = (await import("@allior/wmake-streamelements-events")) as unknown as {
37
- testMessages: Record<string, unknown>;
38
- testAlerts: Record<string, unknown>;
39
- };
40
- runGenerateFields({
41
- fieldsDir: path.resolve(fieldsDir),
42
- testMessages: mod.testMessages,
43
- testAlerts: mod.testAlerts,
44
- });
45
- } catch (e) {
46
- console.error((e as Error).message);
47
- process.exit(1);
48
- }
49
- });
50
-
51
- program
52
- .command("extract-test-data")
53
- .description("No-op: test data lives in streamelements/src/assets as TS objects")
54
- .action(async () => {
55
- try {
56
- await runExtractTestData();
57
- } catch (e) {
58
- console.error((e as Error).message);
59
- process.exit(1);
60
- }
61
- });
62
-
63
- program
64
- .command("base64")
65
- .description("Convert images, videos, SVG to base64 for browsers")
66
- .argument("<path>", "File or directory path")
67
- .option("-o, --output <path>", "Output file or directory")
68
- .option("-f, --full", "Output with additional info")
69
- .action(async (inputPath: string, options: { output?: string; full?: boolean }) => {
70
- if (!fs.existsSync(inputPath)) {
71
- console.error("Error: Path does not exist");
72
- process.exit(1);
73
- }
74
- try {
75
- await processPath(inputPath, options.output ?? null, options.full ?? false);
76
- } catch (e) {
77
- console.error("Error:", (e as Error).message);
78
- process.exit(1);
79
- }
39
+ .description("Generate fields.json from fields.base.json (manual source update)")
40
+ .action(() => {
41
+ runGenerateFields(process.cwd());
80
42
  });
81
43
 
82
44
  program.parse();