@allior/wmake-cli 0.0.4 → 0.0.6

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/index.d.ts CHANGED
@@ -1,7 +1,3 @@
1
- /**
2
- * Библиотека экспортов для использования в других пакетах (например, в Vite конфигах).
3
- * ВАЖНО: Не запускает CLI автоматически при импорте.
4
- */
5
1
  export * from "./vite-config.js";
6
2
  export { buildWidget } from "./widget.js";
7
3
  export { runGenerateFields } from "./generate-fields.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,3 @@
1
- /**
2
- * Библиотека экспортов для использования в других пакетах (например, в Vite конфигах).
3
- * ВАЖНО: Не запускает CLI автоматически при импорте.
4
- */
5
1
  export * from "./vite-config.js";
6
2
  export { buildWidget } from "./widget.js";
7
3
  export { runGenerateFields } from "./generate-fields.js";
@@ -1,22 +1,17 @@
1
- import { PluginOption } from "vite";
2
- export declare const CDN_BASE = "https://cdn.jsdelivr.net/npm";
3
- export declare const REACT_VER = "19.0.0";
4
- export declare const WMAKE_VER = "1.0.0";
5
- export declare const EXTERNAL_FOR_CDN: Set<string>;
6
- export declare function wmakeImportMapPlugin(): PluginOption;
7
- export declare function getWmakeAliases(root: string): {
8
- "@allior/wmake-streamelements-events/react": string;
9
- "@allior/wmake-streamelements-events": string;
10
- "@allior/wmake-utils/react": string;
11
- "@allior/wmake-utils": string;
12
- "@allior/wmake-emotes/react": string;
13
- "@allior/wmake-emotes/7tv": string;
14
- "@allior/wmake-emotes": string;
15
- "@allior/wmake-streamelements/react": string;
16
- "@allior/wmake-streamelements/fields": string;
17
- "@allior/wmake-streamelements": string;
18
- };
19
- export declare function getWmakeOptimizeDeps(): {
20
- include: string[];
21
- };
1
+ import type { PluginOption } from "vite";
2
+ /** Генерирует карту глобалов для Rollup. Используем чистые имена. */
3
+ export declare function getWmakeGlobals(cwd?: string): Record<string, string>;
4
+ /** Вспомогательная функция для получения ЧИСТЫХ имен глобалов (без window.) для проверок */
5
+ export declare function getRawWmakeGlobals(cwd?: string): Record<string, string>;
6
+ /** Получает Set внешних зависимостей для CDN режима */
7
+ export declare function getExternalForCdn(cwd?: string): Set<string>;
8
+ /** Реактивная настройка алиасов для разработки (локальные пути) */
9
+ export declare function getWmakeAliases(root: string, cwd?: string): Record<string, string>;
10
+ /** Оптимизация Vite (чтобы он не пересобирал их сто раз) */
11
+ export declare function getWmakeOptimizeDeps(cwd?: string): string[];
12
+ /** Плагин для вставки тегов <script> из CDN в HTML.txt */
13
+ export declare function wmakeScriptCdnPlugin(options: {
14
+ useCdn: boolean;
15
+ projectDir?: string;
16
+ }): PluginOption;
22
17
  //# sourceMappingURL=vite-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"vite-config.d.ts","sourceRoot":"","sources":["../src/vite-config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAEpC,eAAO,MAAM,QAAQ,iCAAiC,CAAC;AACvD,eAAO,MAAM,SAAS,WAAW,CAAC;AAClC,eAAO,MAAM,SAAS,UAAU,CAAC;AAEjC,eAAO,MAAM,gBAAgB,aAW3B,CAAC;AA4CH,wBAAgB,oBAAoB,IAAI,YAAY,CAmDnD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM;;;;;;;;;;;EAa3C;AAED,wBAAgB,oBAAoB;;EASnC"}
1
+ {"version":3,"file":"vite-config.d.ts","sourceRoot":"","sources":["../src/vite-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AA0CzC,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,0BAQ1D;AAED,4FAA4F;AAC5F,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAsB,0BAQ7D;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAsB,GAAG,GAAG,CAAC,MAAM,CAAC,CAQ1E;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,0BASxE;AAED,4DAA4D;AAC5D,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAsB,YAO/D;AAED,0DAA0D;AAC1D,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,YAAY,CAsDf"}
@@ -1,127 +1,137 @@
1
- import path from "node:path";
2
1
  import fs from "node:fs";
3
- export const CDN_BASE = "https://cdn.jsdelivr.net/npm";
4
- export const REACT_VER = "19.0.0";
5
- export const WMAKE_VER = "1.0.0";
6
- export const EXTERNAL_FOR_CDN = new Set([
7
- "react",
8
- "react/jsx-runtime",
9
- "react-dom",
10
- "react-dom/client",
11
- "@allior/wmake-utils",
12
- "@allior/wmake-utils/react",
13
- "@allior/wmake-streamelements-events",
14
- "@allior/wmake-streamelements-events/react",
15
- "@allior/wmake-emotes/7tv",
16
- "@allior/wmake-streamelements",
17
- ]);
18
- const BOOTSTRAP_PLACEHOLDER_SRC = "__MAIN_SCRIPT_SRC__";
19
- const BOOTSTRAP_PLACEHOLDER_VER = "__DEFAULT_WMAKE_VER__";
20
- const bootstrapScript = `
21
- (function(){
22
- var CDN_BASE='${CDN_BASE}';
23
- var REACT_VER='${REACT_VER}';
24
- var defaultVer='${BOOTSTRAP_PLACEHOLDER_VER}';
25
- var mainScriptSrc='${BOOTSTRAP_PLACEHOLDER_SRC}';
26
- function run(ver){
27
- var v=ver||defaultVer;
28
- var map={imports:{
29
- 'react':CDN_BASE+'/react@'+REACT_VER+'/+esm',
30
- 'react/jsx-runtime':CDN_BASE+'/react@'+REACT_VER+'/jsx-runtime.js',
31
- 'react-dom':CDN_BASE+'/react-dom@'+REACT_VER+'/+esm',
32
- 'react-dom/client':CDN_BASE+'/react-dom@'+REACT_VER+'/client.js',
33
- '@allior/wmake-utils':CDN_BASE+'/@allior/wmake-utils@'+v+'/dist/root/index.js',
34
- '@allior/wmake-utils/react':CDN_BASE+'/@allior/wmake-utils@'+v+'/dist/react/index.js',
35
- '@allior/wmake-streamelements-events':CDN_BASE+'/@allior/wmake-streamelements-events@'+v+'/dist/root/index.js',
36
- '@allior/wmake-streamelements-events/react':CDN_BASE+'/@allior/wmake-streamelements-events@'+v+'/dist/react/index.js',
37
- '@allior/wmake-emotes/7tv':CDN_BASE+'/@allior/wmake-emotes@'+v+'/dist/7tv/index.js',
38
- '@allior/wmake-streamelements':CDN_BASE+'/@allior/wmake-streamelements@'+v+'/dist/root/index.js'
39
- }};
40
- var s=document.createElement('script');
41
- s.type='importmap';
42
- s.textContent=JSON.stringify(map);
43
- document.head.appendChild(s);
44
- var m=document.createElement('script');
45
- m.type='module';
46
- m.src=mainScriptSrc;
47
- document.body.appendChild(m);
48
- }
49
- if(typeof window.addEventListener==='function'){
50
- window.addEventListener('onWidgetLoad',function(obj){
51
- var fd=obj.detail&&obj.detail.fieldData;
52
- run(fd&&fd.wmakeVersion);
53
- });
54
- setTimeout(function(){if(!document.querySelector('script[type="importmap"]'))run(defaultVer);},100);
55
- }else{run(defaultVer);}
56
- })();
57
- `;
58
- export function wmakeImportMapPlugin() {
59
- const imports = {
60
- react: `${CDN_BASE}/react@${REACT_VER}/+esm`,
61
- "react/jsx-runtime": `${CDN_BASE}/react@${REACT_VER}/jsx-runtime.js`,
62
- "react-dom": `${CDN_BASE}/react-dom@${REACT_VER}/+esm`,
63
- "react-dom/client": `${CDN_BASE}/react-dom@${REACT_VER}/client.js`,
64
- "@allior/wmake-utils": `${CDN_BASE}/@allior/wmake-utils@${WMAKE_VER}/dist/root/index.js`,
65
- "@allior/wmake-utils/react": `${CDN_BASE}/@allior/wmake-utils@${WMAKE_VER}/dist/react/index.js`,
66
- "@allior/wmake-streamelements-events": `${CDN_BASE}/@allior/wmake-streamelements-events@${WMAKE_VER}/dist/root/index.js`,
67
- "@allior/wmake-streamelements-events/react": `${CDN_BASE}/@allior/wmake-streamelements-events@${WMAKE_VER}/dist/react/index.js`,
68
- "@allior/wmake-emotes/7tv": `${CDN_BASE}/@allior/wmake-emotes@${WMAKE_VER}/dist/7tv/index.js`,
69
- "@allior/wmake-streamelements": `${CDN_BASE}/@allior/wmake-streamelements@${WMAKE_VER}/dist/root/index.js`,
70
- };
71
- const importMap = { imports };
72
- const staticImportMapScript = `<script type="importmap">${JSON.stringify(importMap)}</script>`;
2
+ import path from "node:path";
3
+ /** Базовые зависимости, которые всегда выносим в CDN (IIFE) */
4
+ const BASE_GLOBALS = {
5
+ react: "React",
6
+ "react-dom": "ReactDOM",
7
+ "react-dom/client": "ReactDOM",
8
+ "react/jsx-runtime": "React",
9
+ };
10
+ /**
11
+ * Преобразует @allior/wmake-something в WmakeSomething
12
+ * @allior/wmake-something/react -> WmakeSomethingReact
13
+ */
14
+ function toGlobalName(pkg) {
15
+ if (pkg.endsWith("/react")) {
16
+ return toGlobalName(pkg.replace("/react", "")) + "React";
17
+ }
18
+ const name = pkg
19
+ .replace("@allior/", "")
20
+ .replace(/\//g, "-")
21
+ .split("-")
22
+ .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
23
+ .join("");
24
+ return name;
25
+ }
26
+ /** Получает список @allior/wmake-* пакетов из депенденси текущего проекта */
27
+ function getWmakeDeps(cwd) {
28
+ const pkgPath = path.join(cwd, "package.json");
29
+ if (!fs.existsSync(pkgPath))
30
+ return [];
31
+ try {
32
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
33
+ const deps = { ...pkg.dependencies };
34
+ return Object.keys(deps).filter((d) => d.startsWith("@allior/wmake-") && d !== "@allior/wmake-cli");
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ }
40
+ /** Генерирует карту глобалов для Rollup. Используем чистые имена. */
41
+ export function getWmakeGlobals(cwd = process.cwd()) {
42
+ const deps = getWmakeDeps(cwd);
43
+ const res = { ...BASE_GLOBALS };
44
+ for (const pkg of deps) {
45
+ res[pkg] = toGlobalName(pkg);
46
+ res[`${pkg}/react`] = toGlobalName(pkg) + "React";
47
+ }
48
+ return res;
49
+ }
50
+ /** Вспомогательная функция для получения ЧИСТЫХ имен глобалов (без window.) для проверок */
51
+ export function getRawWmakeGlobals(cwd = process.cwd()) {
52
+ const deps = getWmakeDeps(cwd);
53
+ const res = { ...BASE_GLOBALS };
54
+ for (const pkg of deps) {
55
+ res[pkg] = toGlobalName(pkg);
56
+ res[`${pkg}/react`] = toGlobalName(pkg) + "React";
57
+ }
58
+ return res;
59
+ }
60
+ /** Получает Set внешних зависимостей для CDN режима */
61
+ export function getExternalForCdn(cwd = process.cwd()) {
62
+ const deps = getWmakeDeps(cwd);
63
+ const res = new Set(Object.keys(BASE_GLOBALS));
64
+ for (const pkg of deps) {
65
+ res.add(pkg);
66
+ res.add(`${pkg}/react`);
67
+ }
68
+ return res;
69
+ }
70
+ /** Реактивная настройка алиасов для разработки (локальные пути) */
71
+ export function getWmakeAliases(root, cwd = process.cwd()) {
72
+ const deps = getWmakeDeps(cwd);
73
+ const aliases = {};
74
+ for (const pkg of deps) {
75
+ const name = pkg.replace("@allior/wmake-", "");
76
+ aliases[pkg] = path.join(root, `${name}/dist/root/index.js`);
77
+ aliases[`${pkg}/react`] = path.join(root, `${name}/dist/react/index.js`);
78
+ }
79
+ return aliases;
80
+ }
81
+ /** Оптимизация Vite (чтобы он не пересобирал их сто раз) */
82
+ export function getWmakeOptimizeDeps(cwd = process.cwd()) {
83
+ const deps = getWmakeDeps(cwd);
84
+ const res = [];
85
+ for (const pkg of deps) {
86
+ res.push(pkg, `${pkg}/react`);
87
+ }
88
+ return res;
89
+ }
90
+ /** Плагин для вставки тегов <script> из CDN в HTML.txt */
91
+ export function wmakeScriptCdnPlugin(options) {
92
+ const { useCdn, projectDir = process.cwd() } = options;
73
93
  return {
74
- name: "importmap-cdn",
94
+ name: "wmake-script-cdn",
75
95
  transformIndexHtml: {
76
96
  order: "post",
77
- handler(html, ctx) {
78
- const isBuild = !ctx.server;
79
- if (isBuild) {
80
- const script = "<script>\n" + bootstrapScript.trim() + "\n</script>";
81
- return html.replace(/(<head[^>]*>)/i, "$1\n" + script);
82
- }
83
- return staticImportMapScript + "\n" + html;
97
+ handler(html) {
98
+ if (!useCdn)
99
+ return html;
100
+ // По требованию пользователя используем React 18.2.0 по умолчанию для совместимости
101
+ const reactVer = "18.2.0";
102
+ const CDN_BASE = "https://cdn.jsdelivr.net/npm";
103
+ // Скрипты реакта - ВСЕГДА В НАЧАЛО
104
+ const reactTags = [
105
+ `<script src="${CDN_BASE}/react@${reactVer}/umd/react.production.min.js"></script>`,
106
+ `<script src="${CDN_BASE}/react-dom@${reactVer}/umd/react-dom.production.min.js"></script>`
107
+ ].join("\n ");
108
+ // Шим для JSX Runtime, чтобы не падал на React.createElement
109
+ const shim = `
110
+ <script>
111
+ (function() {
112
+ var r = function() { return window.React; };
113
+ window.ReactJSXRuntime = {
114
+ get jsx() { return r().createElement; },
115
+ get jsxs() { return r().createElement; },
116
+ get Fragment() { return r().Fragment; }
117
+ };
118
+ })();
119
+ </script>`;
120
+ // Остальные библиотеки @allior/wmake-*
121
+ const deps = getWmakeDeps(projectDir);
122
+ const otherTags = deps.map(pkg => {
123
+ return [
124
+ `<script src="${CDN_BASE}/${pkg}@latest/dist/root/index.iife.js"></script>`,
125
+ `<script src="${CDN_BASE}/${pkg}@latest/dist/react/index.iife.js"></script>`
126
+ ].join("\n ");
127
+ }).join("\n ");
128
+ // Вставляем В НАЧАЛО <head>, чтобы зависимости были первыми
129
+ let res = html.replace(/(<head[^>]*>)/i, `$1\n ${reactTags}${shim ? "\n " + shim : ""}\n ${otherTags}`);
130
+ // Для работы в Streamelements нам НЕ НУЖЕН тег основного скрипта в HTML,
131
+ // так как код живет во вкладке JS. Удаляем его вместе с атрибутами type="module" и crossorigin.
132
+ res = res.replace(/<script(?=[^>]*src=["']\/assets\/index\.js["'])[\s\S]*?><\/script>/gi, '');
133
+ return res;
84
134
  },
85
135
  },
86
- writeBundle(options) {
87
- const outDir = options.dir ?? "dist";
88
- const htmlPath = path.join(outDir, "index.html");
89
- if (!fs.existsSync(htmlPath))
90
- return;
91
- let html = fs.readFileSync(htmlPath, "utf-8");
92
- const scriptTagMatch = html.match(/<script(?=[^>]*type=["']module["'])(?=[^>]*src=)[^>]*src=["']([^"']+)["'][^>]*>\s*<\/script>/);
93
- if (!scriptTagMatch)
94
- return;
95
- const mainScriptSrc = scriptTagMatch[1];
96
- html = html
97
- .replace(BOOTSTRAP_PLACEHOLDER_VER, WMAKE_VER)
98
- .replace(BOOTSTRAP_PLACEHOLDER_SRC, mainScriptSrc)
99
- .replace(scriptTagMatch[0], "");
100
- fs.writeFileSync(htmlPath, html);
101
- },
102
- };
103
- }
104
- export function getWmakeAliases(root) {
105
- return {
106
- "@allior/wmake-streamelements-events/react": path.join(root, "streamelements-events/dist/react/index.js"),
107
- "@allior/wmake-streamelements-events": path.join(root, "streamelements-events/dist/root/index.js"),
108
- "@allior/wmake-utils/react": path.join(root, "utils/dist/react/index.js"),
109
- "@allior/wmake-utils": path.join(root, "utils/dist/root/index.js"),
110
- "@allior/wmake-emotes/react": path.join(root, "emotes/dist/react/index.js"),
111
- "@allior/wmake-emotes/7tv": path.join(root, "emotes/dist/7tv/index.js"),
112
- "@allior/wmake-emotes": path.join(root, "emotes/dist/root/index.js"),
113
- "@allior/wmake-streamelements/react": path.join(root, "streamelements/dist/react/index.js"),
114
- "@allior/wmake-streamelements/fields": path.join(root, "streamelements/dist/fields/index.js"),
115
- "@allior/wmake-streamelements": path.join(root, "streamelements/dist/root/index.js"),
116
- };
117
- }
118
- export function getWmakeOptimizeDeps() {
119
- return {
120
- include: [
121
- "@allior/wmake-streamelements-events",
122
- "@allior/wmake-utils",
123
- "@allior/wmake-emotes/7tv",
124
- "@allior/wmake-streamelements",
125
- ],
126
136
  };
127
137
  }
@@ -1 +1 @@
1
- {"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAwCA,wBAAsB,WAAW,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0I5E"}
1
+ {"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAwCA,wBAAsB,WAAW,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA+K5E"}
package/dist/widget.js CHANGED
@@ -85,7 +85,44 @@ export async function buildWidget(options) {
85
85
  if (jsFiles.length === 0 || cssFiles.length === 0) {
86
86
  throw new Error("Expected .js and .css in dist/assets");
87
87
  }
88
- fs.writeFileSync(path.join(buildDir, "js.txt"), fs.readFileSync(jsFiles[0], "utf-8"));
88
+ let finalJs = fs.readFileSync(jsFiles[0], "utf-8");
89
+ // Если мы НЕ в FULL режиме, оборачиваем в проверку готовности глобалов
90
+ if (!options.full) {
91
+ const { getRawWmakeGlobals } = await import("./vite-config.js");
92
+ const rawGlobals = getRawWmakeGlobals(projectDir);
93
+ 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
+ })();`;
124
+ }
125
+ fs.writeFileSync(path.join(buildDir, "js.txt"), finalJs);
89
126
  fs.writeFileSync(path.join(buildDir, "css.txt"), fs.readFileSync(cssFiles[0], "utf-8"));
90
127
  const fieldsJsonPath = path.join(projectDir, "fields.json");
91
128
  if (fs.existsSync(fieldsJsonPath)) {
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@allior/wmake-cli",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Streamiby/wmake CLI: build widgets, base64 encode assets, generate fields",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
+ "exports": {
8
+ ".": "./dist/index.js",
9
+ "./vite-config": "./dist/vite-config.js",
10
+ "./vite-plugin": "./dist/vite-config.js"
11
+ },
7
12
  "bin": {
8
13
  "wmake-cli": "dist/bin.js",
9
14
  "@allior/wmake-cli": "dist/bin.js"
@@ -1,141 +1,156 @@
1
- import path from "node:path";
1
+ import type { PluginOption } from "vite";
2
2
  import fs from "node:fs";
3
- import { PluginOption } from "vite";
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";
8
-
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);
53
- }
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
- };
3
+ import path from "node:path";
77
4
 
78
- const importMap = { imports };
79
- const staticImportMapScript = `<script type="importmap">${JSON.stringify(importMap)}</script>`;
5
+ /** Базовые зависимости, которые всегда выносим в CDN (IIFE) */
6
+ const BASE_GLOBALS: Record<string, string> = {
7
+ react: "React",
8
+ "react-dom": "ReactDOM",
9
+ "react-dom/client": "ReactDOM",
10
+ "react/jsx-runtime": "React",
11
+ };
80
12
 
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);
90
- }
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;
13
+ /**
14
+ * Преобразует @allior/wmake-something в WmakeSomething
15
+ * @allior/wmake-something/react -> WmakeSomethingReact
16
+ */
17
+ function toGlobalName(pkg: string): string {
18
+ if (pkg.endsWith("/react")) {
19
+ return toGlobalName(pkg.replace("/react", "")) + "React";
20
+ }
21
+ const name = pkg
22
+ .replace("@allior/", "")
23
+ .replace(/\//g, "-")
24
+ .split("-")
25
+ .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
26
+ .join("");
27
+ return name;
28
+ }
98
29
 
99
- let html = fs.readFileSync(htmlPath, "utf-8");
100
- const scriptTagMatch = html.match(
101
- /<script(?=[^>]*type=["']module["'])(?=[^>]*src=)[^>]*src=["']([^"']+)["'][^>]*>\s*<\/script>/,
102
- );
30
+ /** Получает список @allior/wmake-* пакетов из депенденси текущего проекта */
31
+ function getWmakeDeps(cwd: string): string[] {
32
+ const pkgPath = path.join(cwd, "package.json");
33
+ if (!fs.existsSync(pkgPath)) return [];
34
+ try {
35
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
36
+ const deps = { ...pkg.dependencies };
37
+ return Object.keys(deps).filter((d) => d.startsWith("@allior/wmake-") && d !== "@allior/wmake-cli");
38
+ } catch {
39
+ return [];
40
+ }
41
+ }
103
42
 
104
- if (!scriptTagMatch) return;
105
- const mainScriptSrc = scriptTagMatch[1];
43
+ /** Генерирует карту глобалов для Rollup. Используем чистые имена. */
44
+ export function getWmakeGlobals(cwd: string = process.cwd()) {
45
+ const deps = getWmakeDeps(cwd);
46
+ const res: Record<string, string> = { ...BASE_GLOBALS };
47
+ for (const pkg of deps) {
48
+ res[pkg] = toGlobalName(pkg);
49
+ res[`${pkg}/react`] = toGlobalName(pkg) + "React";
50
+ }
51
+ return res;
52
+ }
106
53
 
107
- html = html
108
- .replace(BOOTSTRAP_PLACEHOLDER_VER, WMAKE_VER)
109
- .replace(BOOTSTRAP_PLACEHOLDER_SRC, mainScriptSrc)
110
- .replace(scriptTagMatch[0], "");
54
+ /** Вспомогательная функция для получения ЧИСТЫХ имен глобалов (без window.) для проверок */
55
+ export function getRawWmakeGlobals(cwd: string = process.cwd()) {
56
+ const deps = getWmakeDeps(cwd);
57
+ const res: Record<string, string> = { ...BASE_GLOBALS };
58
+ for (const pkg of deps) {
59
+ res[pkg] = toGlobalName(pkg);
60
+ res[`${pkg}/react`] = toGlobalName(pkg) + "React";
61
+ }
62
+ return res;
63
+ }
111
64
 
112
- fs.writeFileSync(htmlPath, html);
113
- },
114
- };
65
+ /** Получает Set внешних зависимостей для CDN режима */
66
+ export function getExternalForCdn(cwd: string = process.cwd()): Set<string> {
67
+ const deps = getWmakeDeps(cwd);
68
+ const res = new Set(Object.keys(BASE_GLOBALS));
69
+ for (const pkg of deps) {
70
+ res.add(pkg);
71
+ res.add(`${pkg}/react`);
72
+ }
73
+ return res;
115
74
  }
116
75
 
117
- export function getWmakeAliases(root: string) {
118
- 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"),
129
- };
76
+ /** Реактивная настройка алиасов для разработки (локальные пути) */
77
+ export function getWmakeAliases(root: string, cwd: string = process.cwd()) {
78
+ const deps = getWmakeDeps(cwd);
79
+ const aliases: Record<string, string> = {};
80
+ for (const pkg of deps) {
81
+ const name = pkg.replace("@allior/wmake-", "");
82
+ aliases[pkg] = path.join(root, `${name}/dist/root/index.js`);
83
+ aliases[`${pkg}/react`] = path.join(root, `${name}/dist/react/index.js`);
84
+ }
85
+ return aliases;
130
86
  }
131
87
 
132
- export function getWmakeOptimizeDeps() {
88
+ /** Оптимизация Vite (чтобы он не пересобирал их сто раз) */
89
+ export function getWmakeOptimizeDeps(cwd: string = process.cwd()) {
90
+ const deps = getWmakeDeps(cwd);
91
+ const res = [];
92
+ for (const pkg of deps) {
93
+ res.push(pkg, `${pkg}/react`);
94
+ }
95
+ return res;
96
+ }
97
+
98
+ /** Плагин для вставки тегов <script> из CDN в HTML.txt */
99
+ export function wmakeScriptCdnPlugin(options: {
100
+ useCdn: boolean;
101
+ projectDir?: string;
102
+ }): PluginOption {
103
+ const { useCdn, projectDir = process.cwd() } = options;
104
+
133
105
  return {
134
- include: [
135
- "@allior/wmake-streamelements-events",
136
- "@allior/wmake-utils",
137
- "@allior/wmake-emotes/7tv",
138
- "@allior/wmake-streamelements",
139
- ],
106
+ name: "wmake-script-cdn",
107
+ transformIndexHtml: {
108
+ order: "post",
109
+ handler(html) {
110
+ if (!useCdn) return html;
111
+
112
+ // По требованию пользователя используем React 18.2.0 по умолчанию для совместимости
113
+ const reactVer = "18.2.0";
114
+
115
+ const CDN_BASE = "https://cdn.jsdelivr.net/npm";
116
+
117
+ // Скрипты реакта - ВСЕГДА В НАЧАЛО
118
+ const reactTags = [
119
+ `<script src="${CDN_BASE}/react@${reactVer}/umd/react.production.min.js"></script>`,
120
+ `<script src="${CDN_BASE}/react-dom@${reactVer}/umd/react-dom.production.min.js"></script>`
121
+ ].join("\n ");
122
+
123
+ // Шим для JSX Runtime, чтобы не падал на React.createElement
124
+ const shim = `
125
+ <script>
126
+ (function() {
127
+ var r = function() { return window.React; };
128
+ window.ReactJSXRuntime = {
129
+ get jsx() { return r().createElement; },
130
+ get jsxs() { return r().createElement; },
131
+ get Fragment() { return r().Fragment; }
132
+ };
133
+ })();
134
+ </script>`;
135
+
136
+ // Остальные библиотеки @allior/wmake-*
137
+ const deps = getWmakeDeps(projectDir);
138
+ const otherTags = deps.map(pkg => {
139
+ return [
140
+ `<script src="${CDN_BASE}/${pkg}@latest/dist/root/index.iife.js"></script>`,
141
+ `<script src="${CDN_BASE}/${pkg}@latest/dist/react/index.iife.js"></script>`
142
+ ].join("\n ");
143
+ }).join("\n ");
144
+
145
+ // Вставляем В НАЧАЛО <head>, чтобы зависимости были первыми
146
+ let res = html.replace(/(<head[^>]*>)/i, `$1\n ${reactTags}${shim ? "\n " + shim : ""}\n ${otherTags}`);
147
+
148
+ // Для работы в Streamelements нам НЕ НУЖЕН тег основного скрипта в HTML,
149
+ // так как код живет во вкладке JS. Удаляем его вместе с атрибутами type="module" и crossorigin.
150
+ res = res.replace(/<script(?=[^>]*src=["']\/assets\/index\.js["'])[\s\S]*?><\/script>/gi, '');
151
+
152
+ return res;
153
+ },
154
+ },
140
155
  };
141
156
  }
package/src/widget.ts CHANGED
@@ -102,10 +102,47 @@ export async function buildWidget(options: { full?: boolean }): Promise<void> {
102
102
  throw new Error("Expected .js and .css in dist/assets");
103
103
  }
104
104
 
105
- fs.writeFileSync(
106
- path.join(buildDir, "js.txt"),
107
- fs.readFileSync(jsFiles[0], "utf-8"),
108
- );
105
+ let finalJs = fs.readFileSync(jsFiles[0], "utf-8");
106
+
107
+ // Если мы НЕ в FULL режиме, оборачиваем в проверку готовности глобалов
108
+ if (!options.full) {
109
+ const { getRawWmakeGlobals } = await import("./vite-config.js");
110
+ const rawGlobals = getRawWmakeGlobals(projectDir);
111
+ const requiredGlobals = JSON.stringify(Array.from(new Set(Object.values(rawGlobals))));
112
+
113
+ finalJs = `(function() {
114
+ var req = ${requiredGlobals};
115
+ function check() {
116
+ var missing = [];
117
+ for (var i = 0; i < req.length; i++) {
118
+ if (!window[req[i]]) { missing.push(req[i]); }
119
+ }
120
+ if (missing.length === 0) {
121
+ console.log("[WMAKE] All dependencies confirmed: " + req.join(", "));
122
+ var run = function() {
123
+ // Принудительно гарантируем наличие переменных в глобальной области
124
+ ${Array.from(new Set(Object.values(rawGlobals))).map(g => `if (!window.${g}) window.${g} = undefined; var ${g} = window.${g};`).join(" ")}
125
+ try {
126
+ ${finalJs}
127
+ } catch (e) {
128
+ console.error("[WMAKE] Runtime error during widget execution:", e);
129
+ }
130
+ };
131
+ run();
132
+ } else {
133
+ if (window.__WMAKE_LOG_MISSING !== missing.join(",")) {
134
+ console.warn("[WMAKE] Waiting for dependencies: " + missing.join(", "));
135
+ window.__WMAKE_LOG_MISSING = missing.join(",");
136
+ }
137
+ setTimeout(check, 100);
138
+ }
139
+ }
140
+ console.log("[WMAKE] Initializing dependency check...");
141
+ check();
142
+ })();`;
143
+ }
144
+
145
+ fs.writeFileSync(path.join(buildDir, "js.txt"), finalJs);
109
146
  fs.writeFileSync(
110
147
  path.join(buildDir, "css.txt"),
111
148
  fs.readFileSync(cssFiles[0], "utf-8"),