@steambrew/ttc 2.6.3 → 2.7.4
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.js +98 -43
- package/package.json +54 -53
- package/pnpm-workspace.yaml +2 -0
- package/src/check-health.ts +14 -1
- package/src/index.ts +3 -2
- package/src/plugin-api.ts +32 -10
- package/src/query-parser.ts +8 -1
- package/src/static-embed.ts +10 -7
- package/src/transpiler.ts +59 -30
package/dist/index.js
CHANGED
|
@@ -4,25 +4,26 @@ import path, { dirname } from 'path';
|
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { readFile } from 'fs/promises';
|
|
6
6
|
import fs, { existsSync, readFile as readFile$1 } from 'fs';
|
|
7
|
-
import
|
|
8
|
-
import json from '@rollup/plugin-json';
|
|
7
|
+
import babel from '@rollup/plugin-babel';
|
|
9
8
|
import commonjs from '@rollup/plugin-commonjs';
|
|
10
|
-
import
|
|
11
|
-
import typescript from '@rollup/plugin-typescript';
|
|
9
|
+
import json from '@rollup/plugin-json';
|
|
12
10
|
import resolve, { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
11
|
+
import replace from '@rollup/plugin-replace';
|
|
13
12
|
import terser from '@rollup/plugin-terser';
|
|
14
|
-
import
|
|
15
|
-
import nodePolyfills from 'rollup-plugin-polyfill-node';
|
|
13
|
+
import typescript from '@rollup/plugin-typescript';
|
|
16
14
|
import url from '@rollup/plugin-url';
|
|
15
|
+
import { rollup } from 'rollup';
|
|
16
|
+
import nodePolyfills from 'rollup-plugin-polyfill-node';
|
|
17
|
+
import { minify_sync } from 'terser';
|
|
17
18
|
import scss from 'rollup-plugin-scss';
|
|
18
19
|
import * as sass from 'sass';
|
|
19
|
-
import injectProcessEnv from 'rollup-plugin-inject-process-env';
|
|
20
20
|
import dotenv from 'dotenv';
|
|
21
|
-
import
|
|
22
|
-
import MagicString from 'magic-string';
|
|
21
|
+
import injectProcessEnv from 'rollup-plugin-inject-process-env';
|
|
23
22
|
import * as parser from '@babel/parser';
|
|
24
|
-
import
|
|
23
|
+
import { createFilter } from '@rollup/pluginutils';
|
|
25
24
|
import * as glob from 'glob';
|
|
25
|
+
import MagicString from 'magic-string';
|
|
26
|
+
import _traverse from '@babel/traverse';
|
|
26
27
|
import { performance as performance$1 } from 'perf_hooks';
|
|
27
28
|
|
|
28
29
|
const Logger = {
|
|
@@ -83,7 +84,7 @@ var BuildType;
|
|
|
83
84
|
BuildType[BuildType["ProdBuild"] = 1] = "ProdBuild";
|
|
84
85
|
})(BuildType || (BuildType = {}));
|
|
85
86
|
const ValidateParameters = (args) => {
|
|
86
|
-
let typeProp = BuildType.DevBuild, targetProp = process.cwd();
|
|
87
|
+
let typeProp = BuildType.DevBuild, targetProp = process.cwd(), isMillennium = false;
|
|
87
88
|
if (args.includes('--help')) {
|
|
88
89
|
PrintParamHelp();
|
|
89
90
|
process.exit();
|
|
@@ -117,10 +118,14 @@ const ValidateParameters = (args) => {
|
|
|
117
118
|
}
|
|
118
119
|
targetProp = args[i + 1];
|
|
119
120
|
}
|
|
121
|
+
if (args[i] == '--millennium-internal') {
|
|
122
|
+
isMillennium = true;
|
|
123
|
+
}
|
|
120
124
|
}
|
|
121
125
|
return {
|
|
122
126
|
type: typeProp,
|
|
123
127
|
targetPlugin: targetProp,
|
|
128
|
+
isMillennium: isMillennium,
|
|
124
129
|
};
|
|
125
130
|
};
|
|
126
131
|
|
|
@@ -149,13 +154,24 @@ const CheckForUpdates = async () => {
|
|
|
149
154
|
});
|
|
150
155
|
};
|
|
151
156
|
|
|
152
|
-
const ValidatePlugin = (target) => {
|
|
157
|
+
const ValidatePlugin = (bIsMillennium, target) => {
|
|
153
158
|
return new Promise((resolve, reject) => {
|
|
154
159
|
if (!existsSync(target)) {
|
|
155
160
|
console.error(chalk.red.bold(`\n[-] --target [${target}] `) + chalk.red('is not a valid system path'));
|
|
156
161
|
reject();
|
|
157
162
|
return;
|
|
158
163
|
}
|
|
164
|
+
if (bIsMillennium) {
|
|
165
|
+
console.log(chalk.green.bold('\n[+] Using Millennium internal build configuration'));
|
|
166
|
+
resolve({
|
|
167
|
+
name: 'core',
|
|
168
|
+
common_name: 'Millennium',
|
|
169
|
+
description: 'An integrated plugin that provides core platform functionality.',
|
|
170
|
+
useBackend: false,
|
|
171
|
+
frontend: '.',
|
|
172
|
+
});
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
159
175
|
const pluginModule = path.join(target, 'plugin.json');
|
|
160
176
|
if (!existsSync(pluginModule)) {
|
|
161
177
|
console.error(chalk.red.bold(`\n[-] --target [${target}] `) + chalk.red('is not a valid plugin (missing plugin.json)'));
|
|
@@ -200,7 +216,7 @@ function ExecutePluginModule() {
|
|
|
200
216
|
}
|
|
201
217
|
/** Expose the OnPluginConfigChange so it can be called externally */
|
|
202
218
|
MillenniumStore.OnPluginConfigChange = OnPluginConfigChange;
|
|
203
|
-
MILLENNIUM_BACKEND_IPC.postMessage(0, { pluginName: pluginName, methodName: '__builtins__.__millennium_plugin_settings_parser__' }).then((response) => {
|
|
219
|
+
MILLENNIUM_BACKEND_IPC.postMessage(0, { pluginName: pluginName, methodName: '__builtins__.__millennium_plugin_settings_parser__' }).then(async (response) => {
|
|
204
220
|
/**
|
|
205
221
|
* __millennium_plugin_settings_parser__ will return false if the plugin has no settings.
|
|
206
222
|
* If the plugin has settings, it will return a base64 encoded string.
|
|
@@ -220,7 +236,7 @@ function ExecutePluginModule() {
|
|
|
220
236
|
__millennium_internal_plugin_name_do_not_use_or_change__: pluginName,
|
|
221
237
|
});
|
|
222
238
|
/** Run the rolled up plugins default exported function */
|
|
223
|
-
let pluginProps = PluginModule.default();
|
|
239
|
+
let pluginProps = await PluginModule.default();
|
|
224
240
|
function isValidSidebarNavComponent(obj) {
|
|
225
241
|
return obj && obj.title !== undefined && obj.icon !== undefined && obj.content !== undefined;
|
|
226
242
|
}
|
|
@@ -293,16 +309,33 @@ function InitializePlugins() {
|
|
|
293
309
|
MillenniumStore.ignoreProxyFlag = false;
|
|
294
310
|
});
|
|
295
311
|
}
|
|
296
|
-
function WebkitInitializeIPC() {
|
|
297
|
-
|
|
298
|
-
|
|
312
|
+
async function WebkitInitializeIPC() {
|
|
313
|
+
let intervalId = null;
|
|
314
|
+
const maxWaitTime = 10000; // 10 seconds
|
|
315
|
+
intervalId = setInterval(() => {
|
|
316
|
+
if (typeof SteamClient === 'undefined') {
|
|
299
317
|
return;
|
|
300
318
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
319
|
+
if (intervalId) {
|
|
320
|
+
clearInterval(intervalId);
|
|
321
|
+
intervalId = null;
|
|
322
|
+
}
|
|
323
|
+
SteamClient.BrowserView?.RegisterForMessageFromParent((messageId, data) => {
|
|
324
|
+
if (messageId !== IPCMessageId) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const payload = JSON.parse(data);
|
|
328
|
+
MillenniumStore.ignoreProxyFlag = true;
|
|
329
|
+
MillenniumStore.settingsStore[payload.name] = payload.value;
|
|
330
|
+
MillenniumStore.ignoreProxyFlag = false;
|
|
331
|
+
});
|
|
332
|
+
}, 100);
|
|
333
|
+
setTimeout(() => {
|
|
334
|
+
if (intervalId) {
|
|
335
|
+
clearInterval(intervalId);
|
|
336
|
+
console.warn('%c Millennium %c Failed to find SteamClient after 10000ms', 'background:rgb(37, 105, 184); color: white;', 'background: transparent;');
|
|
337
|
+
}
|
|
338
|
+
}, maxWaitTime);
|
|
306
339
|
}
|
|
307
340
|
isClientModule ? ClientInitializeIPC() : WebkitInitializeIPC();
|
|
308
341
|
const StartSettingPropagation = (name, value) => {
|
|
@@ -362,6 +395,7 @@ function InitializePlugins() {
|
|
|
362
395
|
MillenniumStore.settingsStore = DefinePluginSetting({});
|
|
363
396
|
}
|
|
364
397
|
|
|
398
|
+
const traverse = _traverse.default;
|
|
365
399
|
const Log = (...message) => {
|
|
366
400
|
console.log(chalk.blueBright.bold('constSysfsExpr'), ...message);
|
|
367
401
|
};
|
|
@@ -629,7 +663,7 @@ function InsertMillennium(type, props) {
|
|
|
629
663
|
continue;
|
|
630
664
|
}
|
|
631
665
|
Logger.Info('millenniumAPI', 'Bundling into ' + ComponentType[type] + ' module... ' + chalk.green.bold('okay'));
|
|
632
|
-
|
|
666
|
+
let code = ConstructFunctions([
|
|
633
667
|
`const MILLENNIUM_IS_CLIENT_MODULE = ${type === ComponentType.Plugin ? 'true' : 'false'};`,
|
|
634
668
|
`const pluginName = "${props.strPluginInternalName}";`,
|
|
635
669
|
InitializePlugins.toString(),
|
|
@@ -640,6 +674,10 @@ function InsertMillennium(type, props) {
|
|
|
640
674
|
ExecutePluginModule.toString(),
|
|
641
675
|
ExecutePluginModule.name + '()',
|
|
642
676
|
]);
|
|
677
|
+
if (props.bTersePlugin) {
|
|
678
|
+
code = minify_sync(code).code ?? code;
|
|
679
|
+
}
|
|
680
|
+
bundle[fileName].code = code;
|
|
643
681
|
}
|
|
644
682
|
};
|
|
645
683
|
return { name: String(), generateBundle };
|
|
@@ -660,9 +698,9 @@ async function MergePluginList(plugins) {
|
|
|
660
698
|
// Merge input plugins with the filtered custom plugins
|
|
661
699
|
return [...plugins, ...filteredCustomPlugins];
|
|
662
700
|
}
|
|
663
|
-
async function GetPluginComponents(props) {
|
|
701
|
+
async function GetPluginComponents(pluginJson, props) {
|
|
664
702
|
let tsConfigPath = '';
|
|
665
|
-
const frontendDir = GetFrontEndDirectory();
|
|
703
|
+
const frontendDir = GetFrontEndDirectory(pluginJson);
|
|
666
704
|
if (frontendDir === '.' || frontendDir === './') {
|
|
667
705
|
tsConfigPath = './tsconfig.json';
|
|
668
706
|
}
|
|
@@ -674,21 +712,23 @@ async function GetPluginComponents(props) {
|
|
|
674
712
|
}
|
|
675
713
|
Logger.Info('millenniumAPI', 'Loading tsconfig from ' + chalk.cyan.bold(tsConfigPath) + '... ' + chalk.green.bold('okay'));
|
|
676
714
|
let pluginList = [
|
|
715
|
+
typescript({
|
|
716
|
+
tsconfig: tsConfigPath,
|
|
717
|
+
compilerOptions: {
|
|
718
|
+
outDir: undefined,
|
|
719
|
+
},
|
|
720
|
+
}),
|
|
677
721
|
url({
|
|
678
722
|
include: ['**/*.gif', '**/*.webm', '**/*.svg'], // Add all non-JS assets you use
|
|
679
723
|
limit: 0, // Set to 0 to always copy the file instead of inlining as base64
|
|
680
724
|
fileName: '[hash][extname]', // Optional: custom output naming
|
|
681
725
|
}),
|
|
682
726
|
InsertMillennium(ComponentType.Plugin, props),
|
|
683
|
-
commonjs(),
|
|
684
|
-
nodePolyfills(),
|
|
685
727
|
nodeResolve({
|
|
686
728
|
browser: true,
|
|
687
729
|
}),
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
tsconfig: tsConfigPath,
|
|
691
|
-
}),
|
|
730
|
+
commonjs(),
|
|
731
|
+
nodePolyfills(),
|
|
692
732
|
scss({
|
|
693
733
|
output: false,
|
|
694
734
|
outputStyle: 'compressed',
|
|
@@ -696,10 +736,8 @@ async function GetPluginComponents(props) {
|
|
|
696
736
|
watch: 'src/styles',
|
|
697
737
|
sass: sass,
|
|
698
738
|
}),
|
|
699
|
-
resolve(),
|
|
700
739
|
json(),
|
|
701
740
|
constSysfsExpr(),
|
|
702
|
-
injectProcessEnv(envVars),
|
|
703
741
|
replace({
|
|
704
742
|
delimiters: ['', ''],
|
|
705
743
|
preventAssignment: true,
|
|
@@ -711,6 +749,9 @@ async function GetPluginComponents(props) {
|
|
|
711
749
|
'client.BindPluginSettings()': 'client.BindPluginSettings(pluginName)',
|
|
712
750
|
}),
|
|
713
751
|
];
|
|
752
|
+
if (envVars.length > 0) {
|
|
753
|
+
pluginList.push(injectProcessEnv(envVars));
|
|
754
|
+
}
|
|
714
755
|
if (props.bTersePlugin) {
|
|
715
756
|
pluginList.push(terser());
|
|
716
757
|
}
|
|
@@ -732,7 +773,6 @@ async function GetWebkitPluginComponents(props) {
|
|
|
732
773
|
commonjs(),
|
|
733
774
|
json(),
|
|
734
775
|
constSysfsExpr(),
|
|
735
|
-
injectProcessEnv(envVars),
|
|
736
776
|
replace({
|
|
737
777
|
delimiters: ['', ''],
|
|
738
778
|
preventAssignment: true,
|
|
@@ -745,23 +785,37 @@ async function GetWebkitPluginComponents(props) {
|
|
|
745
785
|
babelHelpers: 'bundled',
|
|
746
786
|
}),
|
|
747
787
|
];
|
|
788
|
+
if (envVars.length > 0) {
|
|
789
|
+
pluginList.push(injectProcessEnv(envVars));
|
|
790
|
+
}
|
|
748
791
|
pluginList = await MergePluginList(pluginList);
|
|
749
792
|
props.bTersePlugin && pluginList.push(terser());
|
|
750
793
|
return pluginList;
|
|
751
794
|
}
|
|
752
|
-
const GetFrontEndDirectory = () => {
|
|
753
|
-
const pluginJsonPath = './plugin.json';
|
|
795
|
+
const GetFrontEndDirectory = (pluginJson) => {
|
|
754
796
|
try {
|
|
755
|
-
return
|
|
797
|
+
return pluginJson?.frontend ?? 'frontend';
|
|
756
798
|
}
|
|
757
799
|
catch (error) {
|
|
758
800
|
return 'frontend';
|
|
759
801
|
}
|
|
760
802
|
};
|
|
761
|
-
const TranspilerPluginComponent = async (props) => {
|
|
803
|
+
const TranspilerPluginComponent = async (bIsMillennium, pluginJson, props) => {
|
|
804
|
+
const frontendDir = GetFrontEndDirectory(pluginJson);
|
|
805
|
+
console.log(chalk.greenBright.bold('config'), 'Frontend directory set to:', chalk.cyan.bold(frontendDir));
|
|
806
|
+
const frontendPlugins = await GetPluginComponents(pluginJson, props);
|
|
807
|
+
// Fix entry file path construction
|
|
808
|
+
let entryFile = '';
|
|
809
|
+
if (frontendDir === '.' || frontendDir === './' || frontendDir === '') {
|
|
810
|
+
entryFile = './index.tsx';
|
|
811
|
+
}
|
|
812
|
+
else {
|
|
813
|
+
entryFile = `./${frontendDir}/index.tsx`;
|
|
814
|
+
}
|
|
815
|
+
console.log(chalk.greenBright.bold('config'), 'Entry file set to:', chalk.cyan.bold(entryFile));
|
|
762
816
|
const frontendRollupConfig = {
|
|
763
|
-
input:
|
|
764
|
-
plugins:
|
|
817
|
+
input: entryFile,
|
|
818
|
+
plugins: frontendPlugins,
|
|
765
819
|
context: 'window',
|
|
766
820
|
external: (id) => {
|
|
767
821
|
if (id === '@steambrew/webkit') {
|
|
@@ -772,7 +826,7 @@ const TranspilerPluginComponent = async (props) => {
|
|
|
772
826
|
},
|
|
773
827
|
output: {
|
|
774
828
|
name: 'millennium_main',
|
|
775
|
-
file: '.millennium/Dist/index.js',
|
|
829
|
+
file: bIsMillennium ? '../../build/frontend.bin' : '.millennium/Dist/index.js',
|
|
776
830
|
globals: {
|
|
777
831
|
react: 'window.SP_REACT',
|
|
778
832
|
'react-dom': 'window.SP_REACTDOM',
|
|
@@ -827,15 +881,16 @@ const CheckModuleUpdates = async () => {
|
|
|
827
881
|
};
|
|
828
882
|
const StartCompilerModule = () => {
|
|
829
883
|
const parameters = ValidateParameters(process.argv.slice(2));
|
|
884
|
+
const bIsMillennium = parameters.isMillennium || false;
|
|
830
885
|
const bTersePlugin = parameters.type == BuildType.ProdBuild;
|
|
831
886
|
console.log(chalk.greenBright.bold('config'), 'Building target:', parameters.targetPlugin, 'with type:', BuildType[parameters.type], 'minify:', bTersePlugin, '...');
|
|
832
|
-
ValidatePlugin(parameters.targetPlugin)
|
|
887
|
+
ValidatePlugin(bIsMillennium, parameters.targetPlugin)
|
|
833
888
|
.then((json) => {
|
|
834
889
|
const props = {
|
|
835
890
|
bTersePlugin: bTersePlugin,
|
|
836
891
|
strPluginInternalName: json?.name,
|
|
837
892
|
};
|
|
838
|
-
TranspilerPluginComponent(props);
|
|
893
|
+
TranspilerPluginComponent(bIsMillennium, json, props);
|
|
839
894
|
})
|
|
840
895
|
/**
|
|
841
896
|
* plugin is invalid, we close the proccess as it has already been handled
|
package/package.json
CHANGED
|
@@ -1,53 +1,54 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@steambrew/ttc",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"millennium-ttc": "dist/index.js"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "rollup -c",
|
|
12
|
-
"prepare": "npm run build"
|
|
13
|
-
},
|
|
14
|
-
"publishConfig": {
|
|
15
|
-
"access": "public"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [],
|
|
18
|
-
"author": "SteamClientHomebrew",
|
|
19
|
-
"license": "MIT",
|
|
20
|
-
"description": "A tiny typescript compiler for Millennium plugins.",
|
|
21
|
-
"dependencies": {
|
|
22
|
-
"@babel/parser": "^7.27.5",
|
|
23
|
-
"@babel/preset-env": "^7.27.2",
|
|
24
|
-
"@babel/preset-react": "^7.27.1",
|
|
25
|
-
"@babel/preset-typescript": "^7.27.1",
|
|
26
|
-
"@babel/traverse": "^7.27.4",
|
|
27
|
-
"@rollup/plugin-babel": "^6.0.4",
|
|
28
|
-
"@rollup/plugin-commonjs": "^28.0.3",
|
|
29
|
-
"@rollup/plugin-json": "^6.1.0",
|
|
30
|
-
"@rollup/plugin-node-resolve": "^15.3.1",
|
|
31
|
-
"@rollup/plugin-replace": "^6.0.2",
|
|
32
|
-
"@rollup/plugin-terser": "^0.4.4",
|
|
33
|
-
"@rollup/plugin-typescript": "^12.1.2",
|
|
34
|
-
"@rollup/plugin-url": "^8.0.2",
|
|
35
|
-
"@rollup/pluginutils": "^5.1.4",
|
|
36
|
-
"chalk": "^5.4.1",
|
|
37
|
-
"dotenv": "^16.5.0",
|
|
38
|
-
"fs": "0.0.1-security",
|
|
39
|
-
"glob": "^11.0.2",
|
|
40
|
-
"magic-string": "^0.30.17",
|
|
41
|
-
"rollup": "^4.42.0",
|
|
42
|
-
"rollup-plugin-inject-process-env": "^1.3.1",
|
|
43
|
-
"rollup-plugin-polyfill-node": "^0.13.0",
|
|
44
|
-
"rollup-plugin-scss": "^4.0.1",
|
|
45
|
-
"sass": "^1.89.1",
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"@types/
|
|
51
|
-
"@types/
|
|
52
|
-
|
|
53
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@steambrew/ttc",
|
|
3
|
+
"version": "2.7.4",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"millennium-ttc": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "rollup -c",
|
|
12
|
+
"prepare": "npm run build"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [],
|
|
18
|
+
"author": "SteamClientHomebrew",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"description": "A tiny typescript compiler for Millennium plugins.",
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@babel/parser": "^7.27.5",
|
|
23
|
+
"@babel/preset-env": "^7.27.2",
|
|
24
|
+
"@babel/preset-react": "^7.27.1",
|
|
25
|
+
"@babel/preset-typescript": "^7.27.1",
|
|
26
|
+
"@babel/traverse": "^7.27.4",
|
|
27
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
28
|
+
"@rollup/plugin-commonjs": "^28.0.3",
|
|
29
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
30
|
+
"@rollup/plugin-node-resolve": "^15.3.1",
|
|
31
|
+
"@rollup/plugin-replace": "^6.0.2",
|
|
32
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
33
|
+
"@rollup/plugin-typescript": "^12.1.2",
|
|
34
|
+
"@rollup/plugin-url": "^8.0.2",
|
|
35
|
+
"@rollup/pluginutils": "^5.1.4",
|
|
36
|
+
"chalk": "^5.4.1",
|
|
37
|
+
"dotenv": "^16.5.0",
|
|
38
|
+
"fs": "0.0.1-security",
|
|
39
|
+
"glob": "^11.0.2",
|
|
40
|
+
"magic-string": "^0.30.17",
|
|
41
|
+
"rollup": "^4.42.0",
|
|
42
|
+
"rollup-plugin-inject-process-env": "^1.3.1",
|
|
43
|
+
"rollup-plugin-polyfill-node": "^0.13.0",
|
|
44
|
+
"rollup-plugin-scss": "^4.0.1",
|
|
45
|
+
"sass": "^1.89.1",
|
|
46
|
+
"terser": "^5.43.1",
|
|
47
|
+
"tslib": "^2.8.1"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/babel__traverse": "^7.20.7",
|
|
51
|
+
"@types/glob": "^8.1.0",
|
|
52
|
+
"@types/node": "^22.15.30"
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/check-health.ts
CHANGED
|
@@ -2,7 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { existsSync, readFile } from 'fs';
|
|
4
4
|
|
|
5
|
-
export const ValidatePlugin = (target: string): Promise<any> => {
|
|
5
|
+
export const ValidatePlugin = (bIsMillennium: boolean, target: string): Promise<any> => {
|
|
6
6
|
return new Promise<any>((resolve, reject) => {
|
|
7
7
|
if (!existsSync(target)) {
|
|
8
8
|
console.error(chalk.red.bold(`\n[-] --target [${target}] `) + chalk.red('is not a valid system path'));
|
|
@@ -10,6 +10,19 @@ export const ValidatePlugin = (target: string): Promise<any> => {
|
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
if (bIsMillennium) {
|
|
14
|
+
console.log(chalk.green.bold('\n[+] Using Millennium internal build configuration'));
|
|
15
|
+
|
|
16
|
+
resolve({
|
|
17
|
+
name: 'core',
|
|
18
|
+
common_name: 'Millennium',
|
|
19
|
+
description: 'An integrated plugin that provides core platform functionality.',
|
|
20
|
+
useBackend: false,
|
|
21
|
+
frontend: '.',
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
const pluginModule = path.join(target, 'plugin.json');
|
|
14
27
|
|
|
15
28
|
if (!existsSync(pluginModule)) {
|
package/src/index.ts
CHANGED
|
@@ -23,18 +23,19 @@ const CheckModuleUpdates = async () => {
|
|
|
23
23
|
|
|
24
24
|
const StartCompilerModule = () => {
|
|
25
25
|
const parameters = ValidateParameters(process.argv.slice(2));
|
|
26
|
+
const bIsMillennium = parameters.isMillennium || false;
|
|
26
27
|
const bTersePlugin = parameters.type == BuildType.ProdBuild;
|
|
27
28
|
|
|
28
29
|
console.log(chalk.greenBright.bold('config'), 'Building target:', parameters.targetPlugin, 'with type:', BuildType[parameters.type], 'minify:', bTersePlugin, '...');
|
|
29
30
|
|
|
30
|
-
ValidatePlugin(parameters.targetPlugin)
|
|
31
|
+
ValidatePlugin(bIsMillennium, parameters.targetPlugin)
|
|
31
32
|
.then((json: any) => {
|
|
32
33
|
const props: TranspilerProps = {
|
|
33
34
|
bTersePlugin: bTersePlugin,
|
|
34
35
|
strPluginInternalName: json?.name,
|
|
35
36
|
};
|
|
36
37
|
|
|
37
|
-
TranspilerPluginComponent(props);
|
|
38
|
+
TranspilerPluginComponent(bIsMillennium, json, props);
|
|
38
39
|
})
|
|
39
40
|
|
|
40
41
|
/**
|
package/src/plugin-api.ts
CHANGED
|
@@ -74,7 +74,7 @@ function ExecutePluginModule() {
|
|
|
74
74
|
/** Expose the OnPluginConfigChange so it can be called externally */
|
|
75
75
|
MillenniumStore.OnPluginConfigChange = OnPluginConfigChange;
|
|
76
76
|
|
|
77
|
-
MILLENNIUM_BACKEND_IPC.postMessage(0, { pluginName: pluginName, methodName: '__builtins__.__millennium_plugin_settings_parser__' }).then((response: any) => {
|
|
77
|
+
MILLENNIUM_BACKEND_IPC.postMessage(0, { pluginName: pluginName, methodName: '__builtins__.__millennium_plugin_settings_parser__' }).then(async (response: any) => {
|
|
78
78
|
/**
|
|
79
79
|
* __millennium_plugin_settings_parser__ will return false if the plugin has no settings.
|
|
80
80
|
* If the plugin has settings, it will return a base64 encoded string.
|
|
@@ -101,7 +101,7 @@ function ExecutePluginModule() {
|
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
/** Run the rolled up plugins default exported function */
|
|
104
|
-
let pluginProps = PluginModule.default();
|
|
104
|
+
let pluginProps = await PluginModule.default();
|
|
105
105
|
|
|
106
106
|
function isValidSidebarNavComponent(obj: any) {
|
|
107
107
|
return obj && obj.title !== undefined && obj.icon !== undefined && obj.content !== undefined;
|
|
@@ -188,17 +188,38 @@ function InitializePlugins() {
|
|
|
188
188
|
});
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
function WebkitInitializeIPC() {
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
async function WebkitInitializeIPC() {
|
|
192
|
+
let intervalId: NodeJS.Timeout | null = null;
|
|
193
|
+
const maxWaitTime = 10000; // 10 seconds
|
|
194
|
+
|
|
195
|
+
intervalId = setInterval(() => {
|
|
196
|
+
if (typeof SteamClient === 'undefined') {
|
|
194
197
|
return;
|
|
195
198
|
}
|
|
196
199
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
if (intervalId) {
|
|
201
|
+
clearInterval(intervalId);
|
|
202
|
+
intervalId = null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
SteamClient.BrowserView?.RegisterForMessageFromParent((messageId: string, data: string) => {
|
|
206
|
+
if (messageId !== IPCMessageId) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const payload = JSON.parse(data);
|
|
211
|
+
MillenniumStore.ignoreProxyFlag = true;
|
|
212
|
+
MillenniumStore.settingsStore[payload.name] = payload.value;
|
|
213
|
+
MillenniumStore.ignoreProxyFlag = false;
|
|
214
|
+
});
|
|
215
|
+
}, 100);
|
|
216
|
+
|
|
217
|
+
setTimeout(() => {
|
|
218
|
+
if (intervalId) {
|
|
219
|
+
clearInterval(intervalId);
|
|
220
|
+
console.warn('%c Millennium %c Failed to find SteamClient after 10000ms', 'background:rgb(37, 105, 184); color: white;', 'background: transparent;');
|
|
221
|
+
}
|
|
222
|
+
}, maxWaitTime);
|
|
202
223
|
}
|
|
203
224
|
|
|
204
225
|
isClientModule ? ClientInitializeIPC() : WebkitInitializeIPC();
|
|
@@ -271,3 +292,4 @@ function InitializePlugins() {
|
|
|
271
292
|
}
|
|
272
293
|
|
|
273
294
|
export { ExecutePluginModule, InitializePlugins };
|
|
295
|
+
|
package/src/query-parser.ts
CHANGED
|
@@ -29,11 +29,13 @@ export enum BuildType {
|
|
|
29
29
|
export interface ParameterProps {
|
|
30
30
|
type: BuildType;
|
|
31
31
|
targetPlugin: string; // path
|
|
32
|
+
isMillennium?: boolean;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
export const ValidateParameters = (args: Array<string>): ParameterProps => {
|
|
35
36
|
let typeProp: BuildType = BuildType.DevBuild,
|
|
36
|
-
targetProp: string = process.cwd()
|
|
37
|
+
targetProp: string = process.cwd(),
|
|
38
|
+
isMillennium: boolean = false;
|
|
37
39
|
|
|
38
40
|
if (args.includes('--help')) {
|
|
39
41
|
PrintParamHelp();
|
|
@@ -73,10 +75,15 @@ export const ValidateParameters = (args: Array<string>): ParameterProps => {
|
|
|
73
75
|
|
|
74
76
|
targetProp = args[i + 1];
|
|
75
77
|
}
|
|
78
|
+
|
|
79
|
+
if (args[i] == '--millennium-internal') {
|
|
80
|
+
isMillennium = true;
|
|
81
|
+
}
|
|
76
82
|
}
|
|
77
83
|
|
|
78
84
|
return {
|
|
79
85
|
type: typeProp,
|
|
80
86
|
targetPlugin: targetProp,
|
|
87
|
+
isMillennium: isMillennium,
|
|
81
88
|
};
|
|
82
89
|
};
|
package/src/static-embed.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { Plugin, SourceDescription, TransformPluginContext } from 'rollup';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { createFilter } from '@rollup/pluginutils';
|
|
5
|
-
import MagicString from 'magic-string';
|
|
6
1
|
import * as parser from '@babel/parser';
|
|
7
|
-
import
|
|
8
|
-
import * as glob from 'glob';
|
|
2
|
+
import { createFilter } from '@rollup/pluginutils';
|
|
9
3
|
import chalk from 'chalk';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import * as glob from 'glob';
|
|
6
|
+
import MagicString from 'magic-string';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { Plugin, SourceDescription, TransformPluginContext } from 'rollup';
|
|
9
|
+
|
|
10
|
+
// Stupid fix because @babel/traverse exports a CommonJS module
|
|
11
|
+
import _traverse from '@babel/traverse';
|
|
12
|
+
const traverse = (_traverse as any).default as typeof _traverse;
|
|
10
13
|
|
|
11
14
|
interface EmbedPluginOptions {
|
|
12
15
|
include?: string | RegExp | (string | RegExp)[];
|
package/src/transpiler.ts
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import
|
|
2
|
-
import json from '@rollup/plugin-json';
|
|
1
|
+
import babel from '@rollup/plugin-babel';
|
|
3
2
|
import commonjs from '@rollup/plugin-commonjs';
|
|
4
|
-
import
|
|
5
|
-
import typescript from '@rollup/plugin-typescript';
|
|
3
|
+
import json from '@rollup/plugin-json';
|
|
6
4
|
import resolve, { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
5
|
+
import replace from '@rollup/plugin-replace';
|
|
7
6
|
import terser from '@rollup/plugin-terser';
|
|
8
|
-
import
|
|
9
|
-
import nodePolyfills from 'rollup-plugin-polyfill-node';
|
|
7
|
+
import typescript from '@rollup/plugin-typescript';
|
|
10
8
|
import url from '@rollup/plugin-url';
|
|
9
|
+
import { InputPluginOption, OutputBundle, OutputOptions, RollupOptions, rollup } from 'rollup';
|
|
10
|
+
import nodePolyfills from 'rollup-plugin-polyfill-node';
|
|
11
|
+
import { minify_sync } from 'terser';
|
|
11
12
|
|
|
12
13
|
import scss from 'rollup-plugin-scss';
|
|
13
14
|
import * as sass from 'sass';
|
|
14
15
|
|
|
15
16
|
import chalk from 'chalk';
|
|
16
|
-
import { Logger } from './logger';
|
|
17
17
|
import fs from 'fs';
|
|
18
|
+
import { Logger } from './logger';
|
|
18
19
|
|
|
19
|
-
import injectProcessEnv from 'rollup-plugin-inject-process-env';
|
|
20
20
|
import dotenv from 'dotenv';
|
|
21
|
+
import injectProcessEnv from 'rollup-plugin-inject-process-env';
|
|
21
22
|
import { ExecutePluginModule, InitializePlugins } from './plugin-api';
|
|
22
23
|
import constSysfsExpr from './static-embed';
|
|
23
24
|
|
|
@@ -54,7 +55,7 @@ export interface TranspilerProps {
|
|
|
54
55
|
const WrappedCallServerMethod = 'const __call_server_method__ = (methodName, kwargs) => Millennium.callServerMethod(pluginName, methodName, kwargs)';
|
|
55
56
|
const WrappedCallable = 'const __wrapped_callable__ = (route) => MILLENNIUM_API.callable(__call_server_method__, route)';
|
|
56
57
|
|
|
57
|
-
const ConstructFunctions = (parts:
|
|
58
|
+
const ConstructFunctions = (parts: string[]): string => {
|
|
58
59
|
return parts.join('\n');
|
|
59
60
|
};
|
|
60
61
|
|
|
@@ -63,8 +64,8 @@ function generate(code: string) {
|
|
|
63
64
|
return `let PluginEntryPointMain = function() { ${code} return millennium_main; };`;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
function InsertMillennium(type: ComponentType, props: TranspilerProps) {
|
|
67
|
-
const generateBundle = (_: unknown, bundle:
|
|
67
|
+
function InsertMillennium(type: ComponentType, props: TranspilerProps): InputPluginOption {
|
|
68
|
+
const generateBundle = (_: unknown, bundle: OutputBundle) => {
|
|
68
69
|
for (const fileName in bundle) {
|
|
69
70
|
if (bundle[fileName].type != 'chunk') {
|
|
70
71
|
continue;
|
|
@@ -72,7 +73,7 @@ function InsertMillennium(type: ComponentType, props: TranspilerProps) {
|
|
|
72
73
|
|
|
73
74
|
Logger.Info('millenniumAPI', 'Bundling into ' + ComponentType[type] + ' module... ' + chalk.green.bold('okay'));
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
let code = ConstructFunctions([
|
|
76
77
|
`const MILLENNIUM_IS_CLIENT_MODULE = ${type === ComponentType.Plugin ? 'true' : 'false'};`,
|
|
77
78
|
`const pluginName = "${props.strPluginInternalName}";`,
|
|
78
79
|
InitializePlugins.toString(),
|
|
@@ -83,6 +84,12 @@ function InsertMillennium(type: ComponentType, props: TranspilerProps) {
|
|
|
83
84
|
ExecutePluginModule.toString(),
|
|
84
85
|
ExecutePluginModule.name + '()',
|
|
85
86
|
]);
|
|
87
|
+
|
|
88
|
+
if (props.bTersePlugin) {
|
|
89
|
+
code = minify_sync(code).code ?? code;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
bundle[fileName].code = code;
|
|
86
93
|
}
|
|
87
94
|
};
|
|
88
95
|
|
|
@@ -112,9 +119,9 @@ async function MergePluginList(plugins: any[]) {
|
|
|
112
119
|
return [...plugins, ...filteredCustomPlugins];
|
|
113
120
|
}
|
|
114
121
|
|
|
115
|
-
async function GetPluginComponents(props: TranspilerProps) {
|
|
122
|
+
async function GetPluginComponents(pluginJson: any, props: TranspilerProps): Promise<InputPluginOption[]> {
|
|
116
123
|
let tsConfigPath = '';
|
|
117
|
-
const frontendDir = GetFrontEndDirectory();
|
|
124
|
+
const frontendDir = GetFrontEndDirectory(pluginJson);
|
|
118
125
|
|
|
119
126
|
if (frontendDir === '.' || frontendDir === './') {
|
|
120
127
|
tsConfigPath = './tsconfig.json';
|
|
@@ -129,21 +136,23 @@ async function GetPluginComponents(props: TranspilerProps) {
|
|
|
129
136
|
Logger.Info('millenniumAPI', 'Loading tsconfig from ' + chalk.cyan.bold(tsConfigPath) + '... ' + chalk.green.bold('okay'));
|
|
130
137
|
|
|
131
138
|
let pluginList = [
|
|
139
|
+
typescript({
|
|
140
|
+
tsconfig: tsConfigPath,
|
|
141
|
+
compilerOptions: {
|
|
142
|
+
outDir: undefined,
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
132
145
|
url({
|
|
133
146
|
include: ['**/*.gif', '**/*.webm', '**/*.svg'], // Add all non-JS assets you use
|
|
134
147
|
limit: 0, // Set to 0 to always copy the file instead of inlining as base64
|
|
135
148
|
fileName: '[hash][extname]', // Optional: custom output naming
|
|
136
149
|
}),
|
|
137
150
|
InsertMillennium(ComponentType.Plugin, props),
|
|
138
|
-
commonjs(),
|
|
139
|
-
nodePolyfills(),
|
|
140
151
|
nodeResolve({
|
|
141
152
|
browser: true,
|
|
142
153
|
}),
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
tsconfig: tsConfigPath,
|
|
146
|
-
}),
|
|
154
|
+
commonjs(),
|
|
155
|
+
nodePolyfills(),
|
|
147
156
|
scss({
|
|
148
157
|
output: false,
|
|
149
158
|
outputStyle: 'compressed',
|
|
@@ -151,10 +160,8 @@ async function GetPluginComponents(props: TranspilerProps) {
|
|
|
151
160
|
watch: 'src/styles',
|
|
152
161
|
sass: sass,
|
|
153
162
|
}),
|
|
154
|
-
resolve(),
|
|
155
163
|
json(),
|
|
156
164
|
constSysfsExpr(),
|
|
157
|
-
injectProcessEnv(envVars),
|
|
158
165
|
replace({
|
|
159
166
|
delimiters: ['', ''],
|
|
160
167
|
preventAssignment: true,
|
|
@@ -167,9 +174,14 @@ async function GetPluginComponents(props: TranspilerProps) {
|
|
|
167
174
|
}),
|
|
168
175
|
];
|
|
169
176
|
|
|
177
|
+
if (envVars.length > 0) {
|
|
178
|
+
pluginList.push(injectProcessEnv(envVars));
|
|
179
|
+
}
|
|
180
|
+
|
|
170
181
|
if (props.bTersePlugin) {
|
|
171
182
|
pluginList.push(terser());
|
|
172
183
|
}
|
|
184
|
+
|
|
173
185
|
return pluginList;
|
|
174
186
|
}
|
|
175
187
|
|
|
@@ -189,7 +201,6 @@ async function GetWebkitPluginComponents(props: TranspilerProps) {
|
|
|
189
201
|
commonjs(),
|
|
190
202
|
json(),
|
|
191
203
|
constSysfsExpr(),
|
|
192
|
-
injectProcessEnv(envVars),
|
|
193
204
|
replace({
|
|
194
205
|
delimiters: ['', ''],
|
|
195
206
|
preventAssignment: true,
|
|
@@ -203,25 +214,43 @@ async function GetWebkitPluginComponents(props: TranspilerProps) {
|
|
|
203
214
|
}),
|
|
204
215
|
];
|
|
205
216
|
|
|
217
|
+
if (envVars.length > 0) {
|
|
218
|
+
pluginList.push(injectProcessEnv(envVars));
|
|
219
|
+
}
|
|
220
|
+
|
|
206
221
|
pluginList = await MergePluginList(pluginList);
|
|
207
222
|
|
|
208
223
|
props.bTersePlugin && pluginList.push(terser());
|
|
209
224
|
return pluginList;
|
|
210
225
|
}
|
|
211
226
|
|
|
212
|
-
const GetFrontEndDirectory = () => {
|
|
213
|
-
const pluginJsonPath = './plugin.json';
|
|
227
|
+
const GetFrontEndDirectory = (pluginJson: any) => {
|
|
214
228
|
try {
|
|
215
|
-
return
|
|
229
|
+
return pluginJson?.frontend ?? 'frontend';
|
|
216
230
|
} catch (error) {
|
|
217
231
|
return 'frontend';
|
|
218
232
|
}
|
|
219
233
|
};
|
|
220
234
|
|
|
221
|
-
export const TranspilerPluginComponent = async (props: TranspilerProps) => {
|
|
235
|
+
export const TranspilerPluginComponent = async (bIsMillennium: boolean, pluginJson: any, props: TranspilerProps) => {
|
|
236
|
+
const frontendDir = GetFrontEndDirectory(pluginJson);
|
|
237
|
+
console.log(chalk.greenBright.bold('config'), 'Frontend directory set to:', chalk.cyan.bold(frontendDir));
|
|
238
|
+
|
|
239
|
+
const frontendPlugins = await GetPluginComponents(pluginJson, props);
|
|
240
|
+
|
|
241
|
+
// Fix entry file path construction
|
|
242
|
+
let entryFile = '';
|
|
243
|
+
if (frontendDir === '.' || frontendDir === './' || frontendDir === '') {
|
|
244
|
+
entryFile = './index.tsx';
|
|
245
|
+
} else {
|
|
246
|
+
entryFile = `./${frontendDir}/index.tsx`;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
console.log(chalk.greenBright.bold('config'), 'Entry file set to:', chalk.cyan.bold(entryFile));
|
|
250
|
+
|
|
222
251
|
const frontendRollupConfig: RollupOptions = {
|
|
223
|
-
input:
|
|
224
|
-
plugins:
|
|
252
|
+
input: entryFile,
|
|
253
|
+
plugins: frontendPlugins,
|
|
225
254
|
context: 'window',
|
|
226
255
|
external: (id) => {
|
|
227
256
|
if (id === '@steambrew/webkit') {
|
|
@@ -235,7 +264,7 @@ export const TranspilerPluginComponent = async (props: TranspilerProps) => {
|
|
|
235
264
|
},
|
|
236
265
|
output: {
|
|
237
266
|
name: 'millennium_main',
|
|
238
|
-
file: '.millennium/Dist/index.js',
|
|
267
|
+
file: bIsMillennium ? '../../build/frontend.bin' : '.millennium/Dist/index.js',
|
|
239
268
|
globals: {
|
|
240
269
|
react: 'window.SP_REACT',
|
|
241
270
|
'react-dom': 'window.SP_REACTDOM',
|