@allior/wmake-cli 0.0.5 → 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.
@@ -1,141 +1,152 @@
1
1
  import path from "node:path";
2
2
  import fs from "node:fs";
3
- import { PluginOption } from "vite";
3
+ import type { AliasOptions, PluginOption } from "vite";
4
4
 
5
- export const CDN_BASE = "https://cdn.jsdelivr.net/npm";
6
- export const REACT_VER = "19.0.0";
7
- export const WMAKE_VER = "1.0.0";
5
+ export const BASE_GLOBALS: Record<string, string> = {
6
+ react: "React",
7
+ "react-dom": "ReactDOM",
8
+ "react-dom/client": "ReactDOM",
9
+ "react/jsx-runtime": "React",
10
+ };
8
11
 
9
- export const EXTERNAL_FOR_CDN = new Set([
10
- "react",
11
- "react/jsx-runtime",
12
- "react-dom",
13
- "react-dom/client",
14
- "@allior/wmake-utils",
15
- "@allior/wmake-utils/react",
16
- "@allior/wmake-streamelements-events",
17
- "@allior/wmake-streamelements-events/react",
18
- "@allior/wmake-emotes/7tv",
19
- "@allior/wmake-streamelements",
20
- ]);
21
-
22
- const BOOTSTRAP_PLACEHOLDER_SRC = "__MAIN_SCRIPT_SRC__";
23
- const BOOTSTRAP_PLACEHOLDER_VER = "__DEFAULT_WMAKE_VER__";
24
-
25
- const bootstrapScript = `
26
- (function(){
27
- var CDN_BASE='${CDN_BASE}';
28
- var REACT_VER='${REACT_VER}';
29
- var defaultVer='${BOOTSTRAP_PLACEHOLDER_VER}';
30
- var mainScriptSrc='${BOOTSTRAP_PLACEHOLDER_SRC}';
31
- function run(ver){
32
- var v=ver||defaultVer;
33
- var map={imports:{
34
- 'react':CDN_BASE+'/react@'+REACT_VER+'/+esm',
35
- 'react/jsx-runtime':CDN_BASE+'/react@'+REACT_VER+'/jsx-runtime.js',
36
- 'react-dom':CDN_BASE+'/react-dom@'+REACT_VER+'/+esm',
37
- 'react-dom/client':CDN_BASE+'/react-dom@'+REACT_VER+'/client.js',
38
- '@allior/wmake-utils':CDN_BASE+'/@allior/wmake-utils@'+v+'/dist/root/index.js',
39
- '@allior/wmake-utils/react':CDN_BASE+'/@allior/wmake-utils@'+v+'/dist/react/index.js',
40
- '@allior/wmake-streamelements-events':CDN_BASE+'/@allior/wmake-streamelements-events@'+v+'/dist/root/index.js',
41
- '@allior/wmake-streamelements-events/react':CDN_BASE+'/@allior/wmake-streamelements-events@'+v+'/dist/react/index.js',
42
- '@allior/wmake-emotes/7tv':CDN_BASE+'/@allior/wmake-emotes@'+v+'/dist/7tv/index.js',
43
- '@allior/wmake-streamelements':CDN_BASE+'/@allior/wmake-streamelements@'+v+'/dist/root/index.js'
44
- }};
45
- var s=document.createElement('script');
46
- s.type='importmap';
47
- s.textContent=JSON.stringify(map);
48
- document.head.appendChild(s);
49
- var m=document.createElement('script');
50
- m.type='module';
51
- m.src=mainScriptSrc;
52
- document.body.appendChild(m);
12
+ /** Translates package name to global window variable name */
13
+ export function getWmakeGlobals(cwd: string = process.cwd()): Record<string, string> {
14
+ const deps = getWmakeDeps(cwd);
15
+ const res: Record<string, string> = { ...BASE_GLOBALS };
16
+ for (const pkg of deps) {
17
+ const name = pkg.replace("@allior/wmake-", "");
18
+ const pascalName = name
19
+ .split("-")
20
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
21
+ .join("");
22
+ res[pkg] = `Wmake${pascalName}`;
23
+ res[`${pkg}/react`] = `Wmake${pascalName}React`;
53
24
  }
54
- if(typeof window.addEventListener==='function'){
55
- window.addEventListener('onWidgetLoad',function(obj){
56
- var fd=obj.detail&&obj.detail.fieldData;
57
- run(fd&&fd.wmakeVersion);
58
- });
59
- setTimeout(function(){if(!document.querySelector('script[type="importmap"]'))run(defaultVer);},100);
60
- }else{run(defaultVer);}
61
- })();
62
- `;
63
-
64
- export function wmakeImportMapPlugin(): PluginOption {
65
- const imports: Record<string, string> = {
66
- react: `${CDN_BASE}/react@${REACT_VER}/+esm`,
67
- "react/jsx-runtime": `${CDN_BASE}/react@${REACT_VER}/jsx-runtime.js`,
68
- "react-dom": `${CDN_BASE}/react-dom@${REACT_VER}/+esm`,
69
- "react-dom/client": `${CDN_BASE}/react-dom@${REACT_VER}/client.js`,
70
- "@allior/wmake-utils": `${CDN_BASE}/@allior/wmake-utils@${WMAKE_VER}/dist/root/index.js`,
71
- "@allior/wmake-utils/react": `${CDN_BASE}/@allior/wmake-utils@${WMAKE_VER}/dist/react/index.js`,
72
- "@allior/wmake-streamelements-events": `${CDN_BASE}/@allior/wmake-streamelements-events@${WMAKE_VER}/dist/root/index.js`,
73
- "@allior/wmake-streamelements-events/react": `${CDN_BASE}/@allior/wmake-streamelements-events@${WMAKE_VER}/dist/react/index.js`,
74
- "@allior/wmake-emotes/7tv": `${CDN_BASE}/@allior/wmake-emotes@${WMAKE_VER}/dist/7tv/index.js`,
75
- "@allior/wmake-streamelements": `${CDN_BASE}/@allior/wmake-streamelements@${WMAKE_VER}/dist/root/index.js`,
76
- };
25
+ return res;
26
+ }
77
27
 
78
- const importMap = { imports };
79
- const staticImportMapScript = `<script type="importmap">${JSON.stringify(importMap)}</script>`;
28
+ /** Translates package name to global window variable name (without React/ReactDOM) */
29
+ export function getRawWmakeGlobals(cwd: string = process.cwd()): Record<string, string> {
30
+ const deps = getWmakeDeps(cwd);
31
+ const res: Record<string, string> = {};
32
+ for (const pkg of deps) {
33
+ const name = pkg.replace("@allior/wmake-", "");
34
+ const pascalName = name
35
+ .split("-")
36
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
37
+ .join("");
38
+ res[pkg] = `Wmake${pascalName}`;
39
+ res[`${pkg}/react`] = `Wmake${pascalName}React`;
40
+ }
41
+ return res;
42
+ }
80
43
 
81
- return {
82
- name: "importmap-cdn",
83
- transformIndexHtml: {
84
- order: "post" as const,
85
- handler(html: string, ctx: { server?: unknown }) {
86
- const isBuild = !ctx.server;
87
- if (isBuild) {
88
- const script = "<script>\n" + bootstrapScript.trim() + "\n</script>";
89
- return html.replace(/(<head[^>]*>)/i, "$1\n" + script);
44
+ /** Generates Vite aliases for workspace development */
45
+ export function getWmakeAliases(root: string): AliasOptions {
46
+ const dirs = fs.readdirSync(root, { withFileTypes: true });
47
+ const aliases: any = {};
48
+ for (const dir of dirs) {
49
+ if (dir.isDirectory()) {
50
+ const pkgPath = path.join(root, dir.name, "package.json");
51
+ if (fs.existsSync(pkgPath)) {
52
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
53
+ if (pkg.name && pkg.name.startsWith("@allior/wmake-")) {
54
+ aliases[pkg.name] = path.resolve(root, dir.name, "dist/root/index.js");
55
+ aliases[`${pkg.name}/react`] = path.resolve(root, dir.name, "dist/react/index.js");
90
56
  }
91
- return staticImportMapScript + "\n" + html;
92
- },
93
- },
94
- writeBundle(options: { dir?: string }) {
95
- const outDir = options.dir ?? "dist";
96
- const htmlPath = path.join(outDir, "index.html");
97
- if (!fs.existsSync(htmlPath)) return;
57
+ }
58
+ }
59
+ }
60
+ return aliases;
61
+ }
98
62
 
99
- let html = fs.readFileSync(htmlPath, "utf-8");
100
- const scriptTagMatch = html.match(
101
- /<script(?=[^>]*type=["']module["'])(?=[^>]*src=)[^>]*src=["']([^"']+)["'][^>]*>\s*<\/script>/,
102
- );
63
+ /** Detects @allior/wmake-* dependencies in package.json and sorts them by hierarchy */
64
+ export function getWmakeDeps(cwd: string = process.cwd()): string[] {
65
+ const pkgPath = path.join(cwd, "package.json");
66
+ if (!fs.existsSync(pkgPath)) return [];
67
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
68
+ const deps = Object.keys(pkg.dependencies || {}).filter((d) => d.startsWith("@allior/wmake-"));
69
+
70
+ return sortWmakeDeps(deps);
71
+ }
72
+
73
+ /** Detects dependencies and their current versions from package.json */
74
+ export function getWmakeDepsWithVersions(cwd: string = process.cwd()): Record<string, string> {
75
+ const pkgPath = path.join(cwd, "package.json");
76
+ if (!fs.existsSync(pkgPath)) return {};
77
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
78
+ const res: Record<string, string> = {};
79
+ const deps = pkg.dependencies || {};
80
+ for (const d in deps) {
81
+ if (d.startsWith("@allior/wmake-")) {
82
+ res[d] = deps[d].replace(/[\^~]/, "");
83
+ }
84
+ }
85
+ return res;
86
+ }
103
87
 
104
- if (!scriptTagMatch) return;
105
- const mainScriptSrc = scriptTagMatch[1];
88
+ /** Checks if a dependency should be external in CDN mode */
89
+ export function isExternalForCdn(id: string, cwd: string = process.cwd()): boolean {
90
+ const normId = id.replace(/\\/g, "/");
91
+ if (Object.keys(BASE_GLOBALS).some(base => id === base || id.startsWith(base + "/"))) return true;
92
+ if (id.startsWith("@allior/wmake-") && id !== "@allior/wmake-cli") return true;
93
+
94
+ const WMAKE_LIBS = ["utils", "streamelements", "streamelements-events", "emotes"];
95
+ for (const lib of WMAKE_LIBS) {
96
+ if (normId.includes(`/${lib}/dist/`)) return true;
97
+ }
98
+
99
+ if (normId.includes("/@allior/wmake-") || normId.includes("/wmake-")) {
100
+ if (!normId.includes("/wmake-cli/")) return true;
101
+ }
102
+ return false;
103
+ }
106
104
 
107
- html = html
108
- .replace(BOOTSTRAP_PLACEHOLDER_VER, WMAKE_VER)
109
- .replace(BOOTSTRAP_PLACEHOLDER_SRC, mainScriptSrc)
110
- .replace(scriptTagMatch[0], "");
105
+ /** Legacy helper for external dependencies */
106
+ export function getExternalForCdn(cwd: string = process.cwd()): string[] {
107
+ const deps = getWmakeDeps(cwd);
108
+ const res = [...Object.keys(BASE_GLOBALS)];
109
+ for (const pkg of deps) {
110
+ res.push(pkg);
111
+ res.push(`${pkg}/react`);
112
+ }
113
+ return res;
114
+ }
111
115
 
112
- fs.writeFileSync(htmlPath, html);
113
- },
114
- };
116
+ /** Provides list of dependencies for pre-optimization */
117
+ export function getWmakeOptimizeDeps(cwd: string = process.cwd()): string[] {
118
+ const deps = getWmakeDeps(cwd);
119
+ return [...deps, ...deps.map((d) => `${d}/react`)];
115
120
  }
116
121
 
117
- export function getWmakeAliases(root: string) {
122
+ /** Vite plugin to inject global window shims for widget development */
123
+ export function wmakeScriptCdnPlugin(options: { useCdn?: boolean } = {}): PluginOption {
124
+ const { useCdn = true } = options;
125
+ if (!useCdn) return { name: "wmake-script-cdn-plugin" };
126
+
118
127
  return {
119
- "@allior/wmake-streamelements-events/react": path.join(root, "streamelements-events/dist/react/index.js"),
120
- "@allior/wmake-streamelements-events": path.join(root, "streamelements-events/dist/root/index.js"),
121
- "@allior/wmake-utils/react": path.join(root, "utils/dist/react/index.js"),
122
- "@allior/wmake-utils": path.join(root, "utils/dist/root/index.js"),
123
- "@allior/wmake-emotes/react": path.join(root, "emotes/dist/react/index.js"),
124
- "@allior/wmake-emotes/7tv": path.join(root, "emotes/dist/7tv/index.js"),
125
- "@allior/wmake-emotes": path.join(root, "emotes/dist/root/index.js"),
126
- "@allior/wmake-streamelements/react": path.join(root, "streamelements/dist/react/index.js"),
127
- "@allior/wmake-streamelements/fields": path.join(root, "streamelements/dist/fields/index.js"),
128
- "@allior/wmake-streamelements": path.join(root, "streamelements/dist/root/index.js"),
128
+ name: "wmake-script-cdn-plugin",
129
+ transformIndexHtml(html: string) {
130
+ return html.replace(
131
+ "</head>",
132
+ `<script src="https://cdn.jsdelivr.net/bundle/npm/react@18.2.0/umd/react.production.min.js"></script>
133
+ <script src="https://cdn.jsdelivr.net/bundle/npm/react-dom@18.2.0/umd/react-dom.production.min.js"></script>
134
+ </head>`
135
+ );
136
+ },
129
137
  };
130
138
  }
131
139
 
132
- export function getWmakeOptimizeDeps() {
133
- return {
134
- include: [
135
- "@allior/wmake-streamelements-events",
136
- "@allior/wmake-utils",
137
- "@allior/wmake-emotes/7tv",
138
- "@allior/wmake-streamelements",
139
- ],
140
- };
140
+ /** Sorts dependencies in correct loading order based on internals */
141
+ export function sortWmakeDeps(deps: string[]): string[] {
142
+ const order = ["utils", "streamelements-events", "emotes", "streamelements"];
143
+ return [...deps].sort((a, b) => {
144
+ const aName = a.replace("@allior/wmake-", "");
145
+ const bName = b.replace("@allior/wmake-", "");
146
+ let aIdx = order.indexOf(aName);
147
+ let bIdx = order.indexOf(bName);
148
+ if (aIdx === -1) aIdx = 999;
149
+ if (bIdx === -1) bIdx = 999;
150
+ return aIdx - bIdx;
151
+ });
141
152
  }
package/src/widget.ts CHANGED
@@ -1,179 +1,155 @@
1
- /**
2
- * Сборка виджета: html.txt, js.txt, css.txt, fields.txt, data.txt и архив .zip.
3
- * Все пути относительно текущей папки (откуда вызывается скрипт).
4
- */
5
- import fs from "node:fs";
6
- import path from "node:path";
7
- import { spawnSync } from "node:child_process";
8
- import {
9
- runGenerateFields,
10
- runGenerateFieldsFromModule,
11
- } from "./generate-fields.js";
12
-
13
- /** Текущая папка (каталог проекта виджета). */
14
- function getProjectDir(): string {
15
- return path.resolve(process.cwd());
16
- }
17
-
18
- function run(
19
- cmd: string,
20
- args: string[],
21
- cwd: string,
22
- env?: NodeJS.ProcessEnv,
23
- ): boolean {
24
- const r = spawnSync(cmd, args, {
25
- cwd,
26
- stdio: "inherit",
27
- shell: true,
28
- env: { ...process.env, ...env },
29
- });
30
- return r.status === 0;
31
- }
32
-
33
- function getPackageManager(): string {
34
- const userAgent = process.env.npm_config_user_agent || "";
35
- if (userAgent.includes("bun")) return "bun";
36
- if (userAgent.includes("pnpm")) return "pnpm";
37
- if (userAgent.includes("yarn")) return "yarn";
38
- return "npm";
39
- }
40
-
41
- export async function buildWidget(options: { full?: boolean }): Promise<void> {
42
- const projectDir = getProjectDir();
43
- const distDir = path.join(projectDir, "dist");
44
- const buildDir = path.resolve(projectDir, process.env.BUILD_DIR ?? "build");
45
- const archiveName = process.env.ARCHIVE_NAME ?? "widget";
46
-
47
- console.log("Generating fields...");
48
- const basePath = path.join(projectDir, "fields.base.json");
49
- const fieldsTsPath = path.join(projectDir, "fields.ts");
50
- if (fs.existsSync(basePath)) {
51
- const mod =
52
- (await import("@allior/wmake-streamelements-events")) as unknown as {
53
- testMessages: Record<string, unknown>;
54
- testAlerts: Record<string, unknown>;
55
- };
56
- runGenerateFields({
57
- fieldsDir: projectDir,
58
- testMessages: mod.testMessages,
59
- testAlerts: mod.testAlerts,
60
- });
61
- } else if (fs.existsSync(fieldsTsPath)) {
62
- runGenerateFieldsFromModule(fieldsTsPath);
63
- } else {
64
- console.log(
65
- "No fields.base.json or fields.ts found, skipping fields generation",
66
- );
67
- }
68
- console.log("Building...");
69
- const buildEnv = options.full ? { BUILD_FULL: "1" } : {};
70
- if (!run(getPackageManager(), ["run", "build"], projectDir, buildEnv)) {
71
- throw new Error("Build failed.");
72
- }
73
-
74
- if (!fs.existsSync(distDir)) {
75
- throw new Error("dist not found. Run build first.");
76
- }
77
-
78
- fs.mkdirSync(buildDir, { recursive: true });
79
-
80
- const html = fs.readFileSync(path.join(distDir, "index.html"), "utf-8");
81
- fs.writeFileSync(path.join(buildDir, "html.txt"), html);
82
-
83
- const assetsDir = path.join(distDir, "assets");
84
- const findFiles = (dir: string, ext: string): string[] => {
85
- const found: string[] = [];
86
- const walk = (d: string) => {
87
- if (!fs.existsSync(d)) return;
88
- for (const e of fs.readdirSync(d)) {
89
- const full = path.join(d, e);
90
- const stat = fs.statSync(full);
91
- if (stat.isDirectory()) walk(full);
92
- else if (e.endsWith(ext)) found.push(full);
93
- }
94
- };
95
- walk(dir);
96
- return found;
97
- };
98
- const jsFiles = findFiles(assetsDir, ".js");
99
- const cssFiles = findFiles(assetsDir, ".css");
100
-
101
- if (jsFiles.length === 0 || cssFiles.length === 0) {
102
- throw new Error("Expected .js and .css in dist/assets");
103
- }
104
-
105
- fs.writeFileSync(
106
- path.join(buildDir, "js.txt"),
107
- fs.readFileSync(jsFiles[0], "utf-8"),
108
- );
109
- fs.writeFileSync(
110
- path.join(buildDir, "css.txt"),
111
- fs.readFileSync(cssFiles[0], "utf-8"),
112
- );
113
-
114
- const fieldsJsonPath = path.join(projectDir, "fields.json");
115
- if (fs.existsSync(fieldsJsonPath)) {
116
- fs.copyFileSync(fieldsJsonPath, path.join(buildDir, "fields.txt"));
117
- }
118
-
119
- const pkgPath = path.join(projectDir, "package.json");
120
- const wmakeVersion =
121
- fs.existsSync(pkgPath) &&
122
- (() => {
123
- try {
124
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
125
- return typeof pkg.version === "string" ? pkg.version : undefined;
126
- } catch {
127
- return undefined;
128
- }
129
- })();
130
- const dataPath = path.join(projectDir, "data.json");
131
- const data = fs.existsSync(dataPath)
132
- ? JSON.parse(fs.readFileSync(dataPath, "utf-8"))
133
- : {};
134
- if (wmakeVersion) {
135
- data.wmakeVersion = wmakeVersion;
136
- }
137
- fs.writeFileSync(
138
- path.join(buildDir, "data.txt"),
139
- JSON.stringify(data, null, 2),
140
- );
141
-
142
- console.log(
143
- "Widget files:",
144
- path.join(buildDir, "html.txt"),
145
- "js.txt, css.txt, fields.txt, data.txt",
146
- );
147
-
148
- const zipPath = path.join(distDir, `${archiveName}.zip`);
149
- const zip = spawnSync("zip", ["-r", zipPath, "."], {
150
- cwd: buildDir,
151
- stdio: "pipe",
152
- });
153
- if (zip.status === 0) {
154
- console.log("Archive:", zipPath);
155
- return;
156
- }
157
- try {
158
- const AdmZip = (await import("adm-zip")).default;
159
- const archive = new AdmZip();
160
- for (const f of [
161
- "html.txt",
162
- "js.txt",
163
- "css.txt",
164
- "fields.txt",
165
- "data.txt",
166
- ]) {
167
- const fp = path.join(buildDir, f);
168
- if (fs.existsSync(fp)) archive.addLocalFile(fp, "", f);
169
- }
170
- archive.writeZip(zipPath);
171
- console.log("Archive (adm-zip):", zipPath);
172
- } catch (e) {
173
- console.error("zip failed and adm-zip fallback error:", e);
174
- console.error(
175
- "Install 'zip' (e.g. apk add zip) or ensure adm-zip is installed.",
176
- );
177
- throw e;
178
- }
179
- }
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { build } from "vite";
4
+ import { getRawWmakeGlobals, getWmakeDeps, getWmakeDepsWithVersions } from "./vite-config.js";
5
+ import { generateMergedFields, GenerateFieldsOptions } from "./generate-fields.js";
6
+ import admZip from "adm-zip";
7
+
8
+ export interface BuildWidgetOptions extends GenerateFieldsOptions {
9
+ full?: boolean;
10
+ seDir?: string;
11
+ }
12
+
13
+ /** Builds project for StreamElements widget using CDN mode */
14
+ export async function buildWidget(options: BuildWidgetOptions = {}) {
15
+ const { full = false, seDir } = options;
16
+ const projectDir = process.cwd();
17
+
18
+ await build({
19
+ configFile: path.resolve(projectDir, "vite.widget.config.ts"),
20
+ build: {
21
+ emptyOutDir: true,
22
+ minify: true,
23
+ }
24
+ });
25
+
26
+ const distDir = path.join(projectDir, "dist");
27
+ const buildDir = path.join(projectDir, "build");
28
+ if (!fs.existsSync(buildDir)) fs.mkdirSync(buildDir, { recursive: true });
29
+
30
+ let html = fs.readFileSync(path.join(distDir, "index.html"), "utf-8");
31
+ let css = fs.readFileSync(path.join(distDir, "assets/style.css"), "utf-8");
32
+ let js = fs.readFileSync(path.join(distDir, "assets/index.js"), "utf-8");
33
+
34
+ if (!full) {
35
+ const rawGlobals = getRawWmakeGlobals(projectDir);
36
+ const requiredGlobals = JSON.stringify(Array.from(new Set(Object.values(rawGlobals))));
37
+ const wmakeDepsWithVersions = getWmakeDepsWithVersions(projectDir);
38
+ const wmakeDeps = getWmakeDeps(projectDir);
39
+ const globalsInOrder = Array.from(new Set(Object.values(rawGlobals)));
40
+
41
+ const loaderJs = `(function() {
42
+ var req = ${requiredGlobals};
43
+ var wmakeDeps = ${JSON.stringify(wmakeDeps)};
44
+ var wmakeFallbacks = ${JSON.stringify(wmakeDepsWithVersions)};
45
+
46
+ for (var i = 0; i < req.length; i++) {
47
+ if (!window.hasOwnProperty(req[i])) window[req[i]] = undefined;
48
+ }
49
+
50
+ function check() {
51
+ var missing = [];
52
+ for (var i = 0; i < req.length; i++) {
53
+ if (!window[req[i]]) { missing.push(req[i]); }
54
+ }
55
+ if (missing.length === 0) {
56
+ console.log("[WMAKE] All context dependencies initialized");
57
+ var run = function() {
58
+ ${globalsInOrder.map(g => `var ${g} = window.${g};`).join(" ")}
59
+ try {
60
+ ${js.trim()}
61
+ } catch (e) {
62
+ console.error("[WMAKE] Runtime error:", e);
63
+ }
64
+ };
65
+ run();
66
+ } else {
67
+ setTimeout(check, 100);
68
+ }
69
+ }
70
+
71
+ function injectScripts(fieldData) {
72
+ var CDN_BASE = "https://cdn.jsdelivr.net/npm";
73
+ var head = document.getElementsByTagName("head")[0];
74
+
75
+ var queue = [];
76
+ for (var i = 0; i < wmakeDeps.length; i++) {
77
+ queue.push({ pkg: wmakeDeps[i], entry: "root" });
78
+ queue.push({ pkg: wmakeDeps[i], entry: "react" });
79
+ }
80
+
81
+ function loadNext(qIdx) {
82
+ if (qIdx >= queue.length) {
83
+ check();
84
+ return;
85
+ }
86
+
87
+ var item = queue[qIdx];
88
+ var pkg = item.pkg;
89
+ var name = pkg.replace("@allior/wmake-", "");
90
+ var pascalName = name.split("-").map(function(w) { return w.charAt(0).toUpperCase() + w.slice(1); }).join("");
91
+ var fieldKey = "wmake" + pascalName + "Version";
92
+ var version = (fieldData && fieldData[fieldKey]) || wmakeFallbacks[pkg] || "latest";
93
+
94
+ var src = CDN_BASE + "/" + pkg + "@" + version + "/dist/" + item.entry + "/index.iife.js";
95
+ var script = document.createElement("script");
96
+ script.src = src;
97
+ script.onload = function() { loadNext(qIdx + 1); };
98
+ script.onerror = function() { loadNext(qIdx + 1); };
99
+ head.appendChild(script);
100
+ }
101
+
102
+ loadNext(0);
103
+ }
104
+
105
+ window.addEventListener("onWidgetLoad", function(obj) {
106
+ var detail = obj.detail;
107
+ window.__WMAKE_INIT_DATA__ = detail;
108
+ injectScripts(detail && detail.fieldData);
109
+ });
110
+ })();`;
111
+
112
+ js = loaderJs;
113
+ }
114
+
115
+ fs.writeFileSync(path.join(buildDir, "html.txt"), html, "utf-8");
116
+ fs.writeFileSync(path.join(buildDir, "css.txt"), css, "utf-8");
117
+ fs.writeFileSync(path.join(buildDir, "js.txt"), js, "utf-8");
118
+
119
+ const fields = generateMergedFields(projectDir, seDir, {
120
+ skipWmakeVersions: options.skipWmakeVersions,
121
+ skipTestAlerts: options.skipTestAlerts,
122
+ skipTestMessages: options.skipTestMessages,
123
+ });
124
+ fs.writeFileSync(path.join(buildDir, "fields.txt"), JSON.stringify(fields, null, 2), "utf-8");
125
+
126
+ const dataPath = seDir
127
+ ? path.join(projectDir, seDir, "data.json")
128
+ : path.join(projectDir, "data.json");
129
+
130
+ let dataFilename = "";
131
+ if (fs.existsSync(dataPath)) {
132
+ dataFilename = "data.txt";
133
+ fs.writeFileSync(path.join(buildDir, dataFilename), fs.readFileSync(dataPath, "utf-8"), "utf-8");
134
+ }
135
+
136
+ const iniContent = `[HTML]
137
+ path = "html.txt"
138
+
139
+ [CSS]
140
+ path = "css.txt"
141
+
142
+ [JS]
143
+ path = "js.txt"
144
+
145
+ [FIELDS]
146
+ path = "fields.txt"
147
+ ${dataFilename ? `\n[DATA]\npath = "${dataFilename}"` : ""}
148
+ `;
149
+ fs.writeFileSync(path.join(buildDir, "widget.ini"), iniContent, "utf-8");
150
+
151
+ const zip = new admZip();
152
+ zip.addLocalFolder(buildDir);
153
+ const zipPath = path.join(distDir, "widget.zip");
154
+ zip.writeZip(zipPath);
155
+ }