@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/bin.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env bun
2
2
  export {};
3
3
  //# sourceMappingURL=bin.d.ts.map
package/dist/bin.js CHANGED
@@ -1,76 +1,38 @@
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
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const pkg = JSON.parse(readFileSync(path.join(__dirname, "../package.json"), "utf8"));
9
10
  const program = new Command();
10
- program.name("wmake").description("CLI for streamiby / wmake").version("1.0.0");
11
+ program
12
+ .name("wmake")
13
+ .description("Build tool for @allior/wmake components")
14
+ .version(pkg.version);
11
15
  program
12
16
  .command("widget")
13
- .description("Build chat-demo into widget files and zip in examples/chat-demo/dist")
14
- .option("--full", "Full bundle (no CDN external), like the old build")
15
- .action(async (opts) => {
16
- try {
17
- await buildWidget({ full: opts.full });
18
- }
19
- catch (e) {
20
- console.error(e.message);
21
- process.exit(1);
22
- }
17
+ .description("Build a StreamElements widget")
18
+ .option("-f, --full", "Build a full bundle without CDN deps")
19
+ .option("-s, --se-dir <dir>", "Directory containing StreamElements files (fields.json, data.json)")
20
+ .option("--no-wmake-versions", "Do not include wmake versions in fields")
21
+ .option("--no-test-alerts", "Do not include test alerts in fields")
22
+ .option("--no-test-messages", "Do not include test messages in fields")
23
+ .action(async (options) => {
24
+ await buildWidget({
25
+ full: options.full,
26
+ seDir: options.seDir,
27
+ skipWmakeVersions: !options.wmakeVersions,
28
+ skipTestAlerts: !options.testAlerts,
29
+ skipTestMessages: !options.testMessages
30
+ });
23
31
  });
24
32
  program
25
33
  .command("generate-fields")
26
- .description("Generate fields.json from fields.base.json and test data objects (WMAKE_FIELDS_DIR)")
27
- .action(async () => {
28
- try {
29
- const fieldsDir = process.env.WMAKE_FIELDS_DIR;
30
- if (!fieldsDir?.trim()) {
31
- throw new Error("WMAKE_FIELDS_DIR must be set.");
32
- }
33
- const mod = (await import("@allior/wmake-streamelements-events"));
34
- runGenerateFields({
35
- fieldsDir: path.resolve(fieldsDir),
36
- testMessages: mod.testMessages,
37
- testAlerts: mod.testAlerts,
38
- });
39
- }
40
- catch (e) {
41
- console.error(e.message);
42
- process.exit(1);
43
- }
44
- });
45
- program
46
- .command("extract-test-data")
47
- .description("No-op: test data lives in streamelements/src/assets as TS objects")
48
- .action(async () => {
49
- try {
50
- await runExtractTestData();
51
- }
52
- catch (e) {
53
- console.error(e.message);
54
- process.exit(1);
55
- }
56
- });
57
- program
58
- .command("base64")
59
- .description("Convert images, videos, SVG to base64 for browsers")
60
- .argument("<path>", "File or directory path")
61
- .option("-o, --output <path>", "Output file or directory")
62
- .option("-f, --full", "Output with additional info")
63
- .action(async (inputPath, options) => {
64
- if (!fs.existsSync(inputPath)) {
65
- console.error("Error: Path does not exist");
66
- process.exit(1);
67
- }
68
- try {
69
- await processPath(inputPath, options.output ?? null, options.full ?? false);
70
- }
71
- catch (e) {
72
- console.error("Error:", e.message);
73
- process.exit(1);
74
- }
34
+ .description("Generate fields.json from fields.base.json (manual source update)")
35
+ .action(() => {
36
+ runGenerateFields(process.cwd());
75
37
  });
76
38
  program.parse();
@@ -1,18 +1,10 @@
1
- /**
2
- * Генерирует fields.json из fields.base.json и ключей из объектов testMessages / testAlerts.
3
- * Путь к каталогу с fields.base.json задаётся WMAKE_FIELDS_DIR.
4
- * Данные сообщений и алертов передаются объектами (из скриптов streamelements).
5
- */
6
- export type MessagesRecord = Record<string, unknown>;
7
- export type AlertsRecord = Record<string, unknown>;
8
- export declare function runGenerateFields(options: {
9
- fieldsDir: string;
10
- testMessages: MessagesRecord;
11
- testAlerts: AlertsRecord;
12
- }): void;
13
- /**
14
- * Генерирует fields.json из TS/JS модуля, экспортирующего default AdvancedField[].
15
- * Использует tsx для загрузки .ts файлов.
16
- */
17
- export declare function runGenerateFieldsFromModule(fieldsModulePath: string): void;
1
+ export interface GenerateFieldsOptions {
2
+ skipWmakeVersions?: boolean;
3
+ skipTestAlerts?: boolean;
4
+ skipTestMessages?: boolean;
5
+ }
6
+ /** Merges base fields with dynamic WMake version fields and testing tools. */
7
+ export declare function generateMergedFields(cwd?: string, seDir?: string, options?: GenerateFieldsOptions): any;
8
+ /** Standalone command entry point */
9
+ export declare function runGenerateFields(cwd?: string): void;
18
10
  //# sourceMappingURL=generate-fields.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate-fields.d.ts","sourceRoot":"","sources":["../src/generate-fields.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgCH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACrD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,cAAc,CAAC;IAC7B,UAAU,EAAE,YAAY,CAAC;CAC1B,GAAG,IAAI,CAkDP;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAiB1E"}
1
+ {"version":3,"file":"generate-fields.d.ts","sourceRoot":"","sources":["../src/generate-fields.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,CAClC,GAAG,GAAE,MAAsB,EAC3B,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,GAAE,qBAA0B,GAClC,GAAG,CA4EL;AAED,qCAAqC;AACrC,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAsB,QAK5D"}
@@ -1,88 +1,81 @@
1
- /**
2
- * Генерирует fields.json из fields.base.json и ключей из объектов testMessages / testAlerts.
3
- * Путь к каталогу с fields.base.json задаётся WMAKE_FIELDS_DIR.
4
- * Данные сообщений и алертов передаются объектами (из скриптов streamelements).
5
- */
6
1
  import fs from "node:fs";
7
2
  import path from "node:path";
8
- import { spawnSync } from "node:child_process";
9
- const TEST_GROUP = "Tests / Тесты";
10
- function pascalCase(s) {
11
- return s.charAt(0).toUpperCase() + s.slice(1);
12
- }
13
- /** camelCase → sentence case (e.g. veryShort → "Very short", selfSub → "Self sub") */
14
- function keyToTitle(key) {
15
- const words = key
16
- .replace(/([A-Z])/g, " $1")
17
- .toLowerCase()
18
- .trim();
19
- return words.charAt(0).toUpperCase() + words.slice(1);
20
- }
21
- function messageLabel(key) {
22
- return `${keyToTitle(key)} message`;
23
- }
24
- function alertLabel(key) {
25
- return `${keyToTitle(key)} alert`;
26
- }
27
- export function runGenerateFields(options) {
28
- const { fieldsDir, testMessages: messages, testAlerts: alerts } = options;
29
- const basePath = path.join(fieldsDir, "fields.base.json");
30
- const outPath = path.join(fieldsDir, "fields.json");
31
- const base = JSON.parse(fs.readFileSync(basePath, "utf-8"));
32
- const messageKeys = Object.keys(messages);
33
- const alertKeys = Object.keys(alerts);
34
- const testMessageFields = {};
35
- for (const key of messageKeys) {
36
- const fieldId = "testMessage" + pascalCase(key);
37
- testMessageFields[fieldId] = {
3
+ import { getWmakeDepsWithVersions } from "./vite-config.js";
4
+ /** Merges base fields with dynamic WMake version fields and testing tools. */
5
+ export function generateMergedFields(cwd = process.cwd(), seDir, options = {}) {
6
+ const baseFieldsPath = seDir
7
+ ? path.join(cwd, seDir, "fields.json")
8
+ : path.join(cwd, "fields.json");
9
+ const legacyPath = path.join(cwd, "fields.base.json");
10
+ let finalBaseFieldsPath = baseFieldsPath;
11
+ if (!fs.existsSync(baseFieldsPath) && fs.existsSync(legacyPath)) {
12
+ finalBaseFieldsPath = legacyPath;
13
+ }
14
+ if (!fs.existsSync(finalBaseFieldsPath)) {
15
+ console.error(`Fields file not found at ${finalBaseFieldsPath}`);
16
+ return {};
17
+ }
18
+ const baseFields = JSON.parse(fs.readFileSync(finalBaseFieldsPath, "utf-8"));
19
+ const finalFields = { ...baseFields };
20
+ const mergedFields = {};
21
+ // 1. Prepare WMake versions
22
+ const wmakeFields = {};
23
+ if (!options.skipWmakeVersions) {
24
+ const wmakeVersions = getWmakeDepsWithVersions(cwd);
25
+ Object.keys(wmakeVersions).forEach(pkg => {
26
+ const name = pkg.replace("@allior/wmake-", "");
27
+ const pascalName = pascalCase(name);
28
+ const fieldKey = `wmake${pascalName}Version`;
29
+ wmakeFields[fieldKey] = {
30
+ type: "text",
31
+ label: `${pascalName} version`,
32
+ value: wmakeVersions[pkg],
33
+ group: "WMake"
34
+ };
35
+ });
36
+ }
37
+ // 2. Prepare Testing fields
38
+ const testFields = {};
39
+ if (!options.skipTestAlerts) {
40
+ testFields["testAlert"] = {
38
41
  type: "button",
39
- label: messageLabel(key),
40
- group: TEST_GROUP,
42
+ label: "Test Alert",
43
+ value: "testAlert",
44
+ group: "Testing"
41
45
  };
42
46
  }
43
- const testAlertFields = {};
44
- for (const key of alertKeys) {
45
- const fieldId = "testAlert" + pascalCase(key);
46
- testAlertFields[fieldId] = {
47
+ if (!options.skipTestMessages) {
48
+ testFields["testMessage"] = {
47
49
  type: "button",
48
- label: alertLabel(key),
49
- group: TEST_GROUP,
50
+ label: "Test Message",
51
+ value: "testMessage",
52
+ group: "Testing"
50
53
  };
51
54
  }
52
- const insertAfterKey = "blueFlowerAnimationDuration";
53
- const result = {};
54
- let inserted = false;
55
- for (const k of Object.keys(base)) {
56
- if (k.startsWith("_"))
57
- continue;
58
- result[k] = base[k];
59
- if (k === insertAfterKey) {
60
- Object.assign(result, testMessageFields, testAlertFields);
61
- inserted = true;
55
+ const dynamicFields = { ...wmakeFields, ...testFields };
56
+ const dynamicKeys = Object.keys(dynamicFields).sort();
57
+ const sortedDynamic = {};
58
+ dynamicKeys.forEach(k => sortedDynamic[k] = dynamicFields[k]);
59
+ let dynamicInserted = false;
60
+ for (const key in finalFields) {
61
+ if (key.startsWith("testMessage") && !dynamicInserted) {
62
+ Object.assign(mergedFields, sortedDynamic);
63
+ dynamicInserted = true;
62
64
  }
65
+ mergedFields[key] = finalFields[key];
63
66
  }
64
- if (!inserted) {
65
- Object.assign(result, testMessageFields, testAlertFields);
67
+ if (!dynamicInserted) {
68
+ Object.assign(mergedFields, sortedDynamic);
66
69
  }
67
- fs.writeFileSync(outPath, JSON.stringify(result, null, 2), "utf-8");
68
- console.log("Wrote", outPath);
69
- console.log("Test message buttons:", messageKeys.length);
70
- console.log("Test alert buttons:", alertKeys.length);
70
+ return mergedFields;
71
71
  }
72
- /**
73
- * Генерирует fields.json из TS/JS модуля, экспортирующего default AdvancedField[].
74
- * Использует tsx для загрузки .ts файлов.
75
- */
76
- export function runGenerateFieldsFromModule(fieldsModulePath) {
77
- const absPath = path.resolve(fieldsModulePath);
78
- const outPath = path.join(path.dirname(absPath), "fields.json");
79
- const runnerPath = path.join(__dirname, "..", "src", "generate-fields-from-module-runner.ts");
80
- const r = spawnSync("npx", ["tsx", runnerPath, absPath, outPath], {
81
- stdio: "inherit",
82
- shell: true,
83
- cwd: path.dirname(absPath),
84
- });
85
- if (r.status !== 0) {
86
- throw new Error(`Failed to generate fields from ${fieldsModulePath}`);
87
- }
72
+ /** Standalone command entry point */
73
+ export function runGenerateFields(cwd = process.cwd()) {
74
+ const fields = generateMergedFields(cwd);
75
+ const fieldsPath = path.join(cwd, "fields.json");
76
+ fs.writeFileSync(fieldsPath, JSON.stringify(fields, null, 2), "utf-8");
77
+ console.log(`Wrote ${fieldsPath}`);
78
+ }
79
+ function pascalCase(str) {
80
+ return str.split("-").map(w => w.charAt(0).toUpperCase() + w.slice(1)).join("");
88
81
  }
@@ -1,17 +1,25 @@
1
- import type { PluginOption } from "vite";
2
- /** Генерирует карту глобалов для Rollup. Используем чистые имена. */
1
+ import type { AliasOptions, PluginOption } from "vite";
2
+ export declare const BASE_GLOBALS: Record<string, string>;
3
+ /** Translates package name to global window variable name */
3
4
  export declare function getWmakeGlobals(cwd?: string): Record<string, string>;
4
- /** Вспомогательная функция для получения ЧИСТЫХ имен глобалов (без window.) для проверок */
5
+ /** Translates package name to global window variable name (without React/ReactDOM) */
5
6
  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 (чтобы он не пересобирал их сто раз) */
7
+ /** Generates Vite aliases for workspace development */
8
+ export declare function getWmakeAliases(root: string): AliasOptions;
9
+ /** Detects @allior/wmake-* dependencies in package.json and sorts them by hierarchy */
10
+ export declare function getWmakeDeps(cwd?: string): string[];
11
+ /** Detects dependencies and their current versions from package.json */
12
+ export declare function getWmakeDepsWithVersions(cwd?: string): Record<string, string>;
13
+ /** Checks if a dependency should be external in CDN mode */
14
+ export declare function isExternalForCdn(id: string, cwd?: string): boolean;
15
+ /** Legacy helper for external dependencies */
16
+ export declare function getExternalForCdn(cwd?: string): string[];
17
+ /** Provides list of dependencies for pre-optimization */
11
18
  export declare function getWmakeOptimizeDeps(cwd?: string): string[];
12
- /** Плагин для вставки тегов <script> из CDN в HTML.txt */
13
- export declare function wmakeScriptCdnPlugin(options: {
14
- useCdn: boolean;
15
- projectDir?: string;
19
+ /** Vite plugin to inject global window shims for widget development */
20
+ export declare function wmakeScriptCdnPlugin(options?: {
21
+ useCdn?: boolean;
16
22
  }): PluginOption;
23
+ /** Sorts dependencies in correct loading order based on internals */
24
+ export declare function sortWmakeDeps(deps: string[]): string[];
17
25
  //# sourceMappingURL=vite-config.d.ts.map
@@ -1 +1 @@
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
+ {"version":3,"file":"vite-config.d.ts","sourceRoot":"","sources":["../src/vite-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAEvD,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAK/C,CAAC;AAEF,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAanF;AAED,sFAAsF;AACtF,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAatF;AAED,uDAAuD;AACvD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAgB1D;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,EAAE,CAOlE;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAY5F;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CAcjF;AAED,8CAA8C;AAC9C,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,EAAE,CAQvE;AAED,yDAAyD;AACzD,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,EAAE,CAG1E;AAED,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,YAAY,CAerF;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAWtD"}
@@ -1,137 +1,142 @@
1
- import fs from "node:fs";
2
1
  import path from "node:path";
3
- /** Базовые зависимости, которые всегда выносим в CDN (IIFE) */
4
- const BASE_GLOBALS = {
2
+ import fs from "node:fs";
3
+ export const BASE_GLOBALS = {
5
4
  react: "React",
6
5
  "react-dom": "ReactDOM",
7
6
  "react-dom/client": "ReactDOM",
8
7
  "react/jsx-runtime": "React",
9
8
  };
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. Используем чистые имена. */
9
+ /** Translates package name to global window variable name */
41
10
  export function getWmakeGlobals(cwd = process.cwd()) {
42
11
  const deps = getWmakeDeps(cwd);
43
12
  const res = { ...BASE_GLOBALS };
44
13
  for (const pkg of deps) {
45
- res[pkg] = toGlobalName(pkg);
46
- res[`${pkg}/react`] = toGlobalName(pkg) + "React";
14
+ const name = pkg.replace("@allior/wmake-", "");
15
+ const pascalName = name
16
+ .split("-")
17
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
18
+ .join("");
19
+ res[pkg] = `Wmake${pascalName}`;
20
+ res[`${pkg}/react`] = `Wmake${pascalName}React`;
47
21
  }
48
22
  return res;
49
23
  }
50
- /** Вспомогательная функция для получения ЧИСТЫХ имен глобалов (без window.) для проверок */
24
+ /** Translates package name to global window variable name (without React/ReactDOM) */
51
25
  export function getRawWmakeGlobals(cwd = process.cwd()) {
52
26
  const deps = getWmakeDeps(cwd);
53
- const res = { ...BASE_GLOBALS };
27
+ const res = {};
54
28
  for (const pkg of deps) {
55
- res[pkg] = toGlobalName(pkg);
56
- res[`${pkg}/react`] = toGlobalName(pkg) + "React";
29
+ const name = pkg.replace("@allior/wmake-", "");
30
+ const pascalName = name
31
+ .split("-")
32
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
33
+ .join("");
34
+ res[pkg] = `Wmake${pascalName}`;
35
+ res[`${pkg}/react`] = `Wmake${pascalName}React`;
57
36
  }
58
37
  return res;
59
38
  }
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`);
39
+ /** Generates Vite aliases for workspace development */
40
+ export function getWmakeAliases(root) {
41
+ const dirs = fs.readdirSync(root, { withFileTypes: true });
42
+ const aliases = {};
43
+ for (const dir of dirs) {
44
+ if (dir.isDirectory()) {
45
+ const pkgPath = path.join(root, dir.name, "package.json");
46
+ if (fs.existsSync(pkgPath)) {
47
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
48
+ if (pkg.name && pkg.name.startsWith("@allior/wmake-")) {
49
+ aliases[pkg.name] = path.resolve(root, dir.name, "dist/root/index.js");
50
+ aliases[`${pkg.name}/react`] = path.resolve(root, dir.name, "dist/react/index.js");
51
+ }
52
+ }
53
+ }
54
+ }
55
+ return aliases;
56
+ }
57
+ /** Detects @allior/wmake-* dependencies in package.json and sorts them by hierarchy */
58
+ export function getWmakeDeps(cwd = process.cwd()) {
59
+ const pkgPath = path.join(cwd, "package.json");
60
+ if (!fs.existsSync(pkgPath))
61
+ return [];
62
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
63
+ const deps = Object.keys(pkg.dependencies || {}).filter((d) => d.startsWith("@allior/wmake-"));
64
+ return sortWmakeDeps(deps);
65
+ }
66
+ /** Detects dependencies and their current versions from package.json */
67
+ export function getWmakeDepsWithVersions(cwd = process.cwd()) {
68
+ const pkgPath = path.join(cwd, "package.json");
69
+ if (!fs.existsSync(pkgPath))
70
+ return {};
71
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
72
+ const res = {};
73
+ const deps = pkg.dependencies || {};
74
+ for (const d in deps) {
75
+ if (d.startsWith("@allior/wmake-")) {
76
+ res[d] = deps[d].replace(/[\^~]/, "");
77
+ }
67
78
  }
68
79
  return res;
69
80
  }
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`);
81
+ /** Checks if a dependency should be external in CDN mode */
82
+ export function isExternalForCdn(id, cwd = process.cwd()) {
83
+ const normId = id.replace(/\\/g, "/");
84
+ if (Object.keys(BASE_GLOBALS).some(base => id === base || id.startsWith(base + "/")))
85
+ return true;
86
+ if (id.startsWith("@allior/wmake-") && id !== "@allior/wmake-cli")
87
+ return true;
88
+ const WMAKE_LIBS = ["utils", "streamelements", "streamelements-events", "emotes"];
89
+ for (const lib of WMAKE_LIBS) {
90
+ if (normId.includes(`/${lib}/dist/`))
91
+ return true;
78
92
  }
79
- return aliases;
93
+ if (normId.includes("/@allior/wmake-") || normId.includes("/wmake-")) {
94
+ if (!normId.includes("/wmake-cli/"))
95
+ return true;
96
+ }
97
+ return false;
80
98
  }
81
- /** Оптимизация Vite (чтобы он не пересобирал их сто раз) */
82
- export function getWmakeOptimizeDeps(cwd = process.cwd()) {
99
+ /** Legacy helper for external dependencies */
100
+ export function getExternalForCdn(cwd = process.cwd()) {
83
101
  const deps = getWmakeDeps(cwd);
84
- const res = [];
102
+ const res = [...Object.keys(BASE_GLOBALS)];
85
103
  for (const pkg of deps) {
86
- res.push(pkg, `${pkg}/react`);
104
+ res.push(pkg);
105
+ res.push(`${pkg}/react`);
87
106
  }
88
107
  return res;
89
108
  }
90
- /** Плагин для вставки тегов <script> из CDN в HTML.txt */
91
- export function wmakeScriptCdnPlugin(options) {
92
- const { useCdn, projectDir = process.cwd() } = options;
109
+ /** Provides list of dependencies for pre-optimization */
110
+ export function getWmakeOptimizeDeps(cwd = process.cwd()) {
111
+ const deps = getWmakeDeps(cwd);
112
+ return [...deps, ...deps.map((d) => `${d}/react`)];
113
+ }
114
+ /** Vite plugin to inject global window shims for widget development */
115
+ export function wmakeScriptCdnPlugin(options = {}) {
116
+ const { useCdn = true } = options;
117
+ if (!useCdn)
118
+ return { name: "wmake-script-cdn-plugin" };
93
119
  return {
94
- name: "wmake-script-cdn",
95
- transformIndexHtml: {
96
- order: "post",
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;
134
- },
120
+ name: "wmake-script-cdn-plugin",
121
+ transformIndexHtml(html) {
122
+ return html.replace("</head>", `<script src="https://cdn.jsdelivr.net/bundle/npm/react@18.2.0/umd/react.production.min.js"></script>
123
+ <script src="https://cdn.jsdelivr.net/bundle/npm/react-dom@18.2.0/umd/react-dom.production.min.js"></script>
124
+ </head>`);
135
125
  },
136
126
  };
137
127
  }
128
+ /** Sorts dependencies in correct loading order based on internals */
129
+ export function sortWmakeDeps(deps) {
130
+ const order = ["utils", "streamelements-events", "emotes", "streamelements"];
131
+ return [...deps].sort((a, b) => {
132
+ const aName = a.replace("@allior/wmake-", "");
133
+ const bName = b.replace("@allior/wmake-", "");
134
+ let aIdx = order.indexOf(aName);
135
+ let bIdx = order.indexOf(bName);
136
+ if (aIdx === -1)
137
+ aIdx = 999;
138
+ if (bIdx === -1)
139
+ bIdx = 999;
140
+ return aIdx - bIdx;
141
+ });
142
+ }
package/dist/widget.d.ts CHANGED
@@ -1,4 +1,8 @@
1
- export declare function buildWidget(options: {
1
+ import { GenerateFieldsOptions } from "./generate-fields.js";
2
+ export interface BuildWidgetOptions extends GenerateFieldsOptions {
2
3
  full?: boolean;
3
- }): Promise<void>;
4
+ seDir?: string;
5
+ }
6
+ /** Builds project for StreamElements widget using CDN mode */
7
+ export declare function buildWidget(options?: BuildWidgetOptions): Promise<void>;
4
8
  //# sourceMappingURL=widget.d.ts.map
@@ -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,CA+K5E"}
1
+ {"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAIA,OAAO,EAAwB,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGnF,MAAM,WAAW,kBAAmB,SAAQ,qBAAqB;IAC/D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,8DAA8D;AAC9D,wBAAsB,WAAW,CAAC,OAAO,GAAE,kBAAuB,iBA6IjE"}