@steambrew/ttc 2.8.7 → 3.0.0
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/.prettierrc +9 -9
- package/bun.lock +680 -0
- package/dist/index.js +310 -460
- package/package.json +55 -54
- package/rollup.config.js +22 -22
- package/src/check-health.ts +53 -54
- package/src/index.ts +53 -61
- package/src/logger.ts +49 -46
- package/src/plugin-api.ts +77 -263
- package/src/query-parser.ts +83 -89
- package/src/static-embed.ts +274 -281
- package/src/transpiler.ts +303 -334
- package/src/version-control.ts +53 -31
- package/tsconfig.json +23 -23
- package/pnpm-workspace.yaml +0 -2
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
+
import fs, { readFileSync, existsSync, readFile as readFile$1 } from 'fs';
|
|
3
4
|
import path, { dirname } from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import { readFile } from 'fs/promises';
|
|
6
|
-
import fs, { existsSync, readFile as readFile$1 } from 'fs';
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
6
|
+
import { readFile, access } from 'fs/promises';
|
|
7
7
|
import babel from '@rollup/plugin-babel';
|
|
8
8
|
import commonjs from '@rollup/plugin-commonjs';
|
|
9
9
|
import json from '@rollup/plugin-json';
|
|
@@ -11,9 +11,10 @@ import resolve, { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
|
11
11
|
import replace from '@rollup/plugin-replace';
|
|
12
12
|
import terser from '@rollup/plugin-terser';
|
|
13
13
|
import typescript from '@rollup/plugin-typescript';
|
|
14
|
+
import esbuild from 'rollup-plugin-esbuild';
|
|
14
15
|
import url from '@rollup/plugin-url';
|
|
15
|
-
import { rollup } from 'rollup';
|
|
16
16
|
import nodePolyfills from 'rollup-plugin-polyfill-node';
|
|
17
|
+
import { rollup } from 'rollup';
|
|
17
18
|
import { minify_sync } from 'terser';
|
|
18
19
|
import scss from 'rollup-plugin-scss';
|
|
19
20
|
import * as sass from 'sass';
|
|
@@ -26,57 +27,53 @@ import MagicString from 'magic-string';
|
|
|
26
27
|
import _traverse from '@babel/traverse';
|
|
27
28
|
import { performance as performance$1 } from 'perf_hooks';
|
|
28
29
|
|
|
30
|
+
const version = JSON.parse(readFileSync(path.resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'), 'utf8')).version;
|
|
29
31
|
const Logger = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
warn(message, loc) {
|
|
33
|
+
if (loc) {
|
|
34
|
+
console.warn(`${chalk.dim(loc + ':')} ${message}`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
console.warn(`${chalk.yellow('warning:')} ${message}`);
|
|
38
|
+
}
|
|
32
39
|
},
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
error(message, loc) {
|
|
41
|
+
if (loc) {
|
|
42
|
+
console.error(`${chalk.dim(loc + ':')} ${message}`);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.error(`${chalk.red('error:')} ${message}`);
|
|
46
|
+
}
|
|
35
47
|
},
|
|
36
|
-
|
|
37
|
-
console.
|
|
48
|
+
update(current, latest, installCmd) {
|
|
49
|
+
console.log(`\n${chalk.yellow('update available')} ${chalk.dim(current)} → ${chalk.green(latest)}`);
|
|
50
|
+
console.log(`${chalk.dim('run:')} ${installCmd}\n`);
|
|
38
51
|
},
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
case 'string':
|
|
50
|
-
color = isLocalPath(value) ? chalk.blueBright : chalk.white;
|
|
51
|
-
break;
|
|
52
|
-
case 'boolean':
|
|
53
|
-
color = chalk.green;
|
|
54
|
-
break;
|
|
55
|
-
case 'number':
|
|
56
|
-
color = chalk.yellow;
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
console.log(chalk.greenBright.bold(`${key}: `).padEnd(fixedPadding), color(String(value)));
|
|
60
|
-
}
|
|
52
|
+
done({ elapsedMs, buildType, sysfsCount, envCount }) {
|
|
53
|
+
const elapsed = `${(elapsedMs / 1000).toFixed(2)}s`;
|
|
54
|
+
const meta = [`ttc v${version}`];
|
|
55
|
+
if (buildType === 'dev')
|
|
56
|
+
meta.push('no type checking');
|
|
57
|
+
if (sysfsCount)
|
|
58
|
+
meta.push(`${sysfsCount} constSysfsExpr`);
|
|
59
|
+
if (envCount)
|
|
60
|
+
meta.push(`${envCount} env var${envCount > 1 ? 's' : ''}`);
|
|
61
|
+
console.log(`${chalk.green('Finished')} ${buildType} in ${elapsed} ` + chalk.dim('(' + meta.join(', ') + ')'));
|
|
61
62
|
},
|
|
62
63
|
};
|
|
63
64
|
|
|
64
|
-
/***
|
|
65
|
-
* @brief print the parameter list to the stdout
|
|
66
|
-
*/
|
|
67
65
|
const PrintParamHelp = () => {
|
|
68
|
-
console.log(
|
|
69
|
-
'
|
|
70
|
-
|
|
71
|
-
'
|
|
72
|
-
'
|
|
73
|
-
|
|
74
|
-
': '
|
|
75
|
-
|
|
76
|
-
'
|
|
77
|
-
'
|
|
78
|
-
|
|
79
|
-
': path to plugin, default to cwd');
|
|
66
|
+
console.log([
|
|
67
|
+
'',
|
|
68
|
+
'usage: millennium-ttc --build <dev|prod> [options]',
|
|
69
|
+
'',
|
|
70
|
+
'options:',
|
|
71
|
+
' --build <dev|prod> build type (prod enables minification)',
|
|
72
|
+
' --target <path> plugin directory (default: current directory)',
|
|
73
|
+
' --no-update skip update check',
|
|
74
|
+
' --help show this message',
|
|
75
|
+
'',
|
|
76
|
+
].join('\n'));
|
|
80
77
|
};
|
|
81
78
|
var BuildType;
|
|
82
79
|
(function (BuildType) {
|
|
@@ -89,9 +86,8 @@ const ValidateParameters = (args) => {
|
|
|
89
86
|
PrintParamHelp();
|
|
90
87
|
process.exit();
|
|
91
88
|
}
|
|
92
|
-
// startup args are invalid
|
|
93
89
|
if (!args.includes('--build')) {
|
|
94
|
-
Logger.
|
|
90
|
+
Logger.error('missing required argument: --build');
|
|
95
91
|
PrintParamHelp();
|
|
96
92
|
process.exit();
|
|
97
93
|
}
|
|
@@ -106,14 +102,14 @@ const ValidateParameters = (args) => {
|
|
|
106
102
|
typeProp = BuildType.ProdBuild;
|
|
107
103
|
break;
|
|
108
104
|
default: {
|
|
109
|
-
Logger.
|
|
105
|
+
Logger.error('--build must be one of: dev, prod');
|
|
110
106
|
process.exit();
|
|
111
107
|
}
|
|
112
108
|
}
|
|
113
109
|
}
|
|
114
110
|
if (args[i] == '--target') {
|
|
115
111
|
if (args[i + 1] === undefined) {
|
|
116
|
-
Logger.
|
|
112
|
+
Logger.error('--target requires a path argument');
|
|
117
113
|
process.exit();
|
|
118
114
|
}
|
|
119
115
|
targetProp = args[i + 1];
|
|
@@ -129,40 +125,61 @@ const ValidateParameters = (args) => {
|
|
|
129
125
|
};
|
|
130
126
|
};
|
|
131
127
|
|
|
128
|
+
async function fileExists(filePath) {
|
|
129
|
+
return access(filePath).then(() => true).catch(() => false);
|
|
130
|
+
}
|
|
131
|
+
async function detectPackageManager() {
|
|
132
|
+
const userAgent = process.env.npm_config_user_agent ?? '';
|
|
133
|
+
if (userAgent.startsWith('bun'))
|
|
134
|
+
return 'bun';
|
|
135
|
+
if (userAgent.startsWith('pnpm'))
|
|
136
|
+
return 'pnpm';
|
|
137
|
+
if (userAgent.startsWith('yarn'))
|
|
138
|
+
return 'yarn';
|
|
139
|
+
const cwd = process.cwd();
|
|
140
|
+
if (await fileExists(path.join(cwd, 'bun.lock')) || await fileExists(path.join(cwd, 'bun.lockb')))
|
|
141
|
+
return 'bun';
|
|
142
|
+
if (await fileExists(path.join(cwd, 'pnpm-lock.yaml')))
|
|
143
|
+
return 'pnpm';
|
|
144
|
+
if (await fileExists(path.join(cwd, 'yarn.lock')))
|
|
145
|
+
return 'yarn';
|
|
146
|
+
return 'npm';
|
|
147
|
+
}
|
|
148
|
+
function installCommand(pm, pkg) {
|
|
149
|
+
switch (pm) {
|
|
150
|
+
case 'bun': return `bun add -d ${pkg}`;
|
|
151
|
+
case 'pnpm': return `pnpm add -D ${pkg}`;
|
|
152
|
+
case 'yarn': return `yarn add -D ${pkg}`;
|
|
153
|
+
default: return `npm i -D ${pkg}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
132
156
|
const CheckForUpdates = async () => {
|
|
133
|
-
|
|
157
|
+
try {
|
|
134
158
|
const packageJsonPath = path.resolve(dirname(fileURLToPath(import.meta.url)), '../package.json');
|
|
135
159
|
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'));
|
|
136
|
-
fetch('https://registry.npmjs.org/@steambrew/ttc')
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
})
|
|
150
|
-
.catch((exception) => {
|
|
151
|
-
Logger.Error('Failed to check for updates: ' + exception);
|
|
152
|
-
resolve(false);
|
|
153
|
-
});
|
|
154
|
-
});
|
|
160
|
+
const response = await fetch('https://registry.npmjs.org/@steambrew/ttc');
|
|
161
|
+
const json = await response.json();
|
|
162
|
+
const latest = json?.['dist-tags']?.latest;
|
|
163
|
+
if (latest && latest !== packageJson.version) {
|
|
164
|
+
const pm = await detectPackageManager();
|
|
165
|
+
Logger.update(packageJson.version, latest, installCommand(pm, `@steambrew/ttc@${latest}`));
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// network or parse failure — silently skip
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
155
173
|
};
|
|
156
174
|
|
|
157
175
|
const ValidatePlugin = (bIsMillennium, target) => {
|
|
158
176
|
return new Promise((resolve, reject) => {
|
|
159
177
|
if (!existsSync(target)) {
|
|
160
|
-
|
|
178
|
+
Logger.error(`target path does not exist: ${target}`);
|
|
161
179
|
reject();
|
|
162
180
|
return;
|
|
163
181
|
}
|
|
164
182
|
if (bIsMillennium) {
|
|
165
|
-
console.log(chalk.green.bold('\n[+] Using Millennium internal build configuration'));
|
|
166
183
|
resolve({
|
|
167
184
|
name: 'core',
|
|
168
185
|
common_name: 'Millennium',
|
|
@@ -174,27 +191,28 @@ const ValidatePlugin = (bIsMillennium, target) => {
|
|
|
174
191
|
}
|
|
175
192
|
const pluginModule = path.join(target, 'plugin.json');
|
|
176
193
|
if (!existsSync(pluginModule)) {
|
|
177
|
-
|
|
194
|
+
Logger.error(`plugin.json not found: ${pluginModule}`);
|
|
178
195
|
reject();
|
|
179
196
|
return;
|
|
180
197
|
}
|
|
181
198
|
readFile$1(pluginModule, 'utf8', (err, data) => {
|
|
182
199
|
if (err) {
|
|
183
|
-
|
|
200
|
+
Logger.error(`could not read plugin.json: ${pluginModule}`);
|
|
184
201
|
reject();
|
|
185
202
|
return;
|
|
186
203
|
}
|
|
187
204
|
try {
|
|
188
|
-
|
|
189
|
-
|
|
205
|
+
const parsed = JSON.parse(data);
|
|
206
|
+
if (!('name' in parsed)) {
|
|
207
|
+
Logger.error('plugin.json is missing required "name" field');
|
|
190
208
|
reject();
|
|
191
209
|
}
|
|
192
210
|
else {
|
|
193
|
-
resolve(
|
|
211
|
+
resolve(parsed);
|
|
194
212
|
}
|
|
195
213
|
}
|
|
196
214
|
catch (parseError) {
|
|
197
|
-
|
|
215
|
+
Logger.error('plugin.json contains invalid JSON:', pluginModule);
|
|
198
216
|
reject();
|
|
199
217
|
}
|
|
200
218
|
});
|
|
@@ -205,178 +223,42 @@ const ValidatePlugin = (bIsMillennium, target) => {
|
|
|
205
223
|
* @description Append the active plugin to the global plugin
|
|
206
224
|
* list and notify that the frontend Loaded.
|
|
207
225
|
*/
|
|
208
|
-
function ExecutePluginModule() {
|
|
209
|
-
let
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
MillenniumStore.ignoreProxyFlag = false;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
/** Expose the OnPluginConfigChange so it can be called externally */
|
|
218
|
-
MillenniumStore.OnPluginConfigChange = OnPluginConfigChange;
|
|
219
|
-
MILLENNIUM_BACKEND_IPC.postMessage(0, { pluginName: pluginName, methodName: '__builtins__.__millennium_plugin_settings_parser__' }).then(async (response) => {
|
|
220
|
-
/**
|
|
221
|
-
* __millennium_plugin_settings_parser__ will return false if the plugin has no settings.
|
|
222
|
-
* If the plugin has settings, it will return a base64 encoded string.
|
|
223
|
-
* The string is then decoded and parsed into an object.
|
|
224
|
-
*/
|
|
225
|
-
if (typeof response.returnValue === 'string') {
|
|
226
|
-
MillenniumStore.ignoreProxyFlag = true;
|
|
227
|
-
/** Initialize the settings store from the settings returned from the backend. */
|
|
228
|
-
MillenniumStore.settingsStore = MillenniumStore.DefinePluginSetting(Object.fromEntries(JSON.parse(atob(response.returnValue)).map((item) => [item.functionName, item])));
|
|
229
|
-
MillenniumStore.ignoreProxyFlag = false;
|
|
230
|
-
}
|
|
231
|
-
/** @ts-ignore: call the plugin main after the settings have been parsed. This prevent plugin settings from being undefined at top level. */
|
|
232
|
-
let PluginModule = PluginEntryPointMain();
|
|
233
|
-
/** Assign the plugin on plugin list. */
|
|
234
|
-
Object.assign(window.PLUGIN_LIST[pluginName], {
|
|
235
|
-
...PluginModule,
|
|
236
|
-
__millennium_internal_plugin_name_do_not_use_or_change__: pluginName,
|
|
237
|
-
});
|
|
238
|
-
/** Run the rolled up plugins default exported function */
|
|
239
|
-
let pluginProps = await PluginModule.default();
|
|
240
|
-
function isValidSidebarNavComponent(obj) {
|
|
241
|
-
return obj && obj.title !== undefined && obj.icon !== undefined && obj.content !== undefined;
|
|
242
|
-
}
|
|
243
|
-
if (pluginProps && isValidSidebarNavComponent(pluginProps)) {
|
|
244
|
-
window.MILLENNIUM_SIDEBAR_NAVIGATION_PANELS[pluginName] = pluginProps;
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
console.warn(`Plugin ${pluginName} does not contain proper SidebarNavigation props and therefor can't be mounted by Millennium. Please ensure it has a title, icon, and content.`);
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
/** If the current module is a client module, post message id=1 which calls the front_end_loaded method on the backend. */
|
|
251
|
-
if (MILLENNIUM_IS_CLIENT_MODULE) {
|
|
252
|
-
MILLENNIUM_BACKEND_IPC.postMessage(1, { pluginName: pluginName });
|
|
253
|
-
}
|
|
226
|
+
async function ExecutePluginModule() {
|
|
227
|
+
let PluginModule = PluginEntryPointMain();
|
|
228
|
+
/** Assign the plugin on plugin list. */
|
|
229
|
+
Object.assign(window.PLUGIN_LIST[pluginName], {
|
|
230
|
+
...PluginModule,
|
|
231
|
+
__millennium_internal_plugin_name_do_not_use_or_change__: pluginName,
|
|
254
232
|
});
|
|
233
|
+
/** Run the rolled up plugins default exported function */
|
|
234
|
+
let pluginProps = await PluginModule.default();
|
|
235
|
+
function isValidSidebarNavComponent(obj) {
|
|
236
|
+
return obj && obj.title !== undefined && obj.icon !== undefined && obj.content !== undefined;
|
|
237
|
+
}
|
|
238
|
+
if (pluginProps && isValidSidebarNavComponent(pluginProps)) {
|
|
239
|
+
window.MILLENNIUM_SIDEBAR_NAVIGATION_PANELS[pluginName] = pluginProps;
|
|
240
|
+
}
|
|
241
|
+
/** If the current module is a client module, post message id=1 which calls the front_end_loaded method on the backend. */
|
|
242
|
+
if (MILLENNIUM_IS_CLIENT_MODULE) {
|
|
243
|
+
MILLENNIUM_BACKEND_IPC.postMessage(1, { pluginName: pluginName });
|
|
244
|
+
}
|
|
255
245
|
}
|
|
256
246
|
/**
|
|
257
247
|
* @description Initialize the plugins settings store and the plugin list.
|
|
258
248
|
* This function is called once per plugin and is used to store the plugin settings and the plugin list.
|
|
259
249
|
*/
|
|
260
250
|
function InitializePlugins() {
|
|
261
|
-
var _a
|
|
262
|
-
/**
|
|
263
|
-
* This function is called n times depending on n plugin count,
|
|
264
|
-
* Create the plugin list if it wasn't already created
|
|
265
|
-
*/
|
|
251
|
+
var _a;
|
|
266
252
|
(_a = (window.PLUGIN_LIST || (window.PLUGIN_LIST = {})))[pluginName] || (_a[pluginName] = {});
|
|
267
|
-
(_b = (window.MILLENNIUM_PLUGIN_SETTINGS_STORE || (window.MILLENNIUM_PLUGIN_SETTINGS_STORE = {})))[pluginName] || (_b[pluginName] = {});
|
|
268
253
|
window.MILLENNIUM_SIDEBAR_NAVIGATION_PANELS || (window.MILLENNIUM_SIDEBAR_NAVIGATION_PANELS = {});
|
|
269
|
-
/**
|
|
270
|
-
* Accepted IPC message types from Millennium backend.
|
|
271
|
-
*/
|
|
272
|
-
let IPCType;
|
|
273
|
-
(function (IPCType) {
|
|
274
|
-
IPCType[IPCType["CallServerMethod"] = 0] = "CallServerMethod";
|
|
275
|
-
})(IPCType || (IPCType = {}));
|
|
276
|
-
let MillenniumStore = window.MILLENNIUM_PLUGIN_SETTINGS_STORE[pluginName];
|
|
277
|
-
let IPCMessageId = `Millennium.Internal.IPC.[${pluginName}]`;
|
|
278
|
-
let isClientModule = MILLENNIUM_IS_CLIENT_MODULE;
|
|
279
|
-
const ComponentTypeMap = {
|
|
280
|
-
DropDown: ['string', 'number', 'boolean'],
|
|
281
|
-
NumberTextInput: ['number'],
|
|
282
|
-
StringTextInput: ['string'],
|
|
283
|
-
FloatTextInput: ['number'],
|
|
284
|
-
CheckBox: ['boolean'],
|
|
285
|
-
NumberSlider: ['number'],
|
|
286
|
-
FloatSlider: ['number'],
|
|
287
|
-
};
|
|
288
|
-
MillenniumStore.ignoreProxyFlag = false;
|
|
289
|
-
function DelegateToBackend(pluginName, name, value) {
|
|
290
|
-
return MILLENNIUM_BACKEND_IPC.postMessage(IPCType.CallServerMethod, {
|
|
291
|
-
pluginName,
|
|
292
|
-
methodName: '__builtins__.__update_settings_value__',
|
|
293
|
-
argumentList: { name, value },
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
async function ClientInitializeIPC() {
|
|
297
|
-
/** Wait for the MainWindowBrowser to not be undefined */
|
|
298
|
-
while (typeof MainWindowBrowserManager === 'undefined') {
|
|
299
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
300
|
-
}
|
|
301
|
-
MainWindowBrowserManager?.m_browser?.on('message', (messageId, data) => {
|
|
302
|
-
if (messageId !== IPCMessageId) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
const { name, value } = JSON.parse(data);
|
|
306
|
-
MillenniumStore.ignoreProxyFlag = true;
|
|
307
|
-
MillenniumStore.settingsStore[name] = value;
|
|
308
|
-
DelegateToBackend(pluginName, name, value);
|
|
309
|
-
MillenniumStore.ignoreProxyFlag = false;
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
if (isClientModule) {
|
|
313
|
-
ClientInitializeIPC();
|
|
314
|
-
}
|
|
315
|
-
const StartSettingPropagation = (name, value) => {
|
|
316
|
-
if (MillenniumStore.ignoreProxyFlag) {
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
if (isClientModule) {
|
|
320
|
-
DelegateToBackend(pluginName, name, value);
|
|
321
|
-
/** If the browser doesn't exist yet, no use sending anything to it. */
|
|
322
|
-
if (typeof MainWindowBrowserManager !== 'undefined') {
|
|
323
|
-
MainWindowBrowserManager?.m_browser?.PostMessage(IPCMessageId, JSON.stringify({ name, value }));
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
else {
|
|
327
|
-
/** Send the message to the SharedJSContext */
|
|
328
|
-
SteamClient.BrowserView.PostMessageToParent(IPCMessageId, JSON.stringify({ name, value }));
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
function clamp(value, min, max) {
|
|
332
|
-
return Math.max(min, Math.min(max, value));
|
|
333
|
-
}
|
|
334
|
-
const DefinePluginSetting = (obj) => {
|
|
335
|
-
return new Proxy(obj, {
|
|
336
|
-
set(target, property, value) {
|
|
337
|
-
if (!(property in target)) {
|
|
338
|
-
throw new TypeError(`Property ${String(property)} does not exist on plugin settings`);
|
|
339
|
-
}
|
|
340
|
-
const settingType = ComponentTypeMap[target[property].type];
|
|
341
|
-
const range = target[property]?.range;
|
|
342
|
-
/** Clamp the value between the given range */
|
|
343
|
-
if (settingType.includes('number') && typeof value === 'number') {
|
|
344
|
-
if (range) {
|
|
345
|
-
value = clamp(value, range[0], range[1]);
|
|
346
|
-
}
|
|
347
|
-
value || (value = 0); // Fallback to 0 if the value is undefined or null
|
|
348
|
-
}
|
|
349
|
-
/** Check if the value is of the proper type */
|
|
350
|
-
if (!settingType.includes(typeof value)) {
|
|
351
|
-
throw new TypeError(`Expected ${settingType.join(' or ')}, got ${typeof value}`);
|
|
352
|
-
}
|
|
353
|
-
target[property].value = value;
|
|
354
|
-
StartSettingPropagation(String(property), value);
|
|
355
|
-
return true;
|
|
356
|
-
},
|
|
357
|
-
get(target, property) {
|
|
358
|
-
if (property === '__raw_get_internals__') {
|
|
359
|
-
return target;
|
|
360
|
-
}
|
|
361
|
-
if (property in target) {
|
|
362
|
-
return target[property].value;
|
|
363
|
-
}
|
|
364
|
-
return undefined;
|
|
365
|
-
},
|
|
366
|
-
});
|
|
367
|
-
};
|
|
368
|
-
MillenniumStore.DefinePluginSetting = DefinePluginSetting;
|
|
369
|
-
MillenniumStore.settingsStore = DefinePluginSetting({});
|
|
370
254
|
}
|
|
371
255
|
|
|
372
256
|
const traverse = _traverse.default;
|
|
373
|
-
const Log = (...message) => {
|
|
374
|
-
console.log(chalk.blueBright.bold('constSysfsExpr'), ...message);
|
|
375
|
-
};
|
|
376
257
|
function constSysfsExpr(options = {}) {
|
|
377
258
|
const filter = createFilter(options.include, options.exclude);
|
|
378
259
|
const pluginName = 'millennium-const-sysfs-expr';
|
|
379
|
-
|
|
260
|
+
let count = 0;
|
|
261
|
+
const plugin = {
|
|
380
262
|
name: pluginName,
|
|
381
263
|
transform(code, id) {
|
|
382
264
|
if (!filter(id))
|
|
@@ -512,7 +394,6 @@ function constSysfsExpr(options = {}) {
|
|
|
512
394
|
return;
|
|
513
395
|
}
|
|
514
396
|
try {
|
|
515
|
-
const currentLocString = node.loc?.start ? ` at ${id}:${node.loc.start.line}:${node.loc.start.column}` : ` in ${id}`;
|
|
516
397
|
const searchBasePath = callOptions.basePath
|
|
517
398
|
? path.isAbsolute(callOptions.basePath)
|
|
518
399
|
? callOptions.basePath
|
|
@@ -521,13 +402,11 @@ function constSysfsExpr(options = {}) {
|
|
|
521
402
|
? path.dirname(pathOrPattern)
|
|
522
403
|
: path.resolve(path.dirname(id), path.dirname(pathOrPattern));
|
|
523
404
|
let embeddedContent;
|
|
524
|
-
let embeddedCount = 0;
|
|
525
405
|
const isPotentialPattern = /[?*+!@()[\]{}]/.test(pathOrPattern);
|
|
526
406
|
if (!isPotentialPattern &&
|
|
527
407
|
fs.existsSync(path.resolve(searchBasePath, pathOrPattern)) &&
|
|
528
408
|
fs.statSync(path.resolve(searchBasePath, pathOrPattern)).isFile()) {
|
|
529
409
|
const singleFilePath = path.resolve(searchBasePath, pathOrPattern);
|
|
530
|
-
Log(`Mode: Single file (first argument "${pathOrPattern}" resolved to "${singleFilePath}" relative to "${searchBasePath}")`);
|
|
531
410
|
try {
|
|
532
411
|
const rawContent = fs.readFileSync(singleFilePath, callOptions.encoding);
|
|
533
412
|
const contentString = rawContent.toString();
|
|
@@ -537,8 +416,6 @@ function constSysfsExpr(options = {}) {
|
|
|
537
416
|
fileName: path.relative(searchBasePath, singleFilePath),
|
|
538
417
|
};
|
|
539
418
|
embeddedContent = JSON.stringify(fileInfo);
|
|
540
|
-
embeddedCount = 1;
|
|
541
|
-
Log(`Embedded 1 specific file for call${currentLocString}`);
|
|
542
419
|
}
|
|
543
420
|
catch (fileError) {
|
|
544
421
|
let message = String(fileError instanceof Error ? fileError.message : fileError ?? 'Unknown file read error');
|
|
@@ -547,8 +424,6 @@ function constSysfsExpr(options = {}) {
|
|
|
547
424
|
}
|
|
548
425
|
}
|
|
549
426
|
else {
|
|
550
|
-
Log(`Mode: Multi-file (first argument "${pathOrPattern}" is pattern or not a single file)`);
|
|
551
|
-
Log(`Searching with pattern "${pathOrPattern}" in directory "${searchBasePath}" (encoding: ${callOptions.encoding})`);
|
|
552
427
|
const matchingFiles = glob.sync(pathOrPattern, {
|
|
553
428
|
cwd: searchBasePath,
|
|
554
429
|
nodir: true,
|
|
@@ -571,15 +446,13 @@ function constSysfsExpr(options = {}) {
|
|
|
571
446
|
}
|
|
572
447
|
}
|
|
573
448
|
embeddedContent = JSON.stringify(fileInfoArray);
|
|
574
|
-
embeddedCount = fileInfoArray.length;
|
|
575
|
-
Log(`Embedded ${embeddedCount} file(s) matching pattern for call${currentLocString}`);
|
|
576
449
|
}
|
|
577
450
|
// Replace the call expression with the generated content string
|
|
578
451
|
magicString.overwrite(node.start, node.end, embeddedContent);
|
|
579
452
|
hasReplaced = true;
|
|
453
|
+
count++;
|
|
580
454
|
}
|
|
581
455
|
catch (error) {
|
|
582
|
-
console.error(`Failed to process files for constSysfsExpr call in ${id}:`, error);
|
|
583
456
|
const message = String(error instanceof Error ? error.message : error ?? 'Unknown error during file processing');
|
|
584
457
|
this.error(`Could not process files for constSysfsExpr: ${message}`, node.loc?.start.index);
|
|
585
458
|
return;
|
|
@@ -589,7 +462,6 @@ function constSysfsExpr(options = {}) {
|
|
|
589
462
|
});
|
|
590
463
|
}
|
|
591
464
|
catch (error) {
|
|
592
|
-
console.error(`Error parsing or traversing ${id}:`, error);
|
|
593
465
|
const message = String(error instanceof Error ? error.message : error ?? 'Unknown parsing error');
|
|
594
466
|
this.error(`Failed to parse ${id}: ${message}`);
|
|
595
467
|
return null;
|
|
@@ -606,207 +478,157 @@ function constSysfsExpr(options = {}) {
|
|
|
606
478
|
return result;
|
|
607
479
|
},
|
|
608
480
|
};
|
|
481
|
+
return { plugin, getCount: () => count };
|
|
609
482
|
}
|
|
610
483
|
|
|
611
|
-
const
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
}, {});
|
|
619
|
-
var ComponentType;
|
|
620
|
-
(function (ComponentType) {
|
|
621
|
-
ComponentType[ComponentType["Plugin"] = 0] = "Plugin";
|
|
622
|
-
ComponentType[ComponentType["Webkit"] = 1] = "Webkit";
|
|
623
|
-
})(ComponentType || (ComponentType = {}));
|
|
624
|
-
const WrappedCallServerMethod = 'const __call_server_method__ = (methodName, kwargs) => Millennium.callServerMethod(pluginName, methodName, kwargs)';
|
|
484
|
+
const env = dotenv.config().parsed ?? {};
|
|
485
|
+
var BuildTarget;
|
|
486
|
+
(function (BuildTarget) {
|
|
487
|
+
BuildTarget[BuildTarget["Plugin"] = 0] = "Plugin";
|
|
488
|
+
BuildTarget[BuildTarget["Webkit"] = 1] = "Webkit";
|
|
489
|
+
})(BuildTarget || (BuildTarget = {}));
|
|
490
|
+
const kCallServerMethod = 'const __call_server_method__ = (methodName, kwargs) => Millennium.callServerMethod(pluginName, methodName, kwargs)';
|
|
625
491
|
function __wrapped_callable__(route) {
|
|
626
492
|
if (route.startsWith('webkit:')) {
|
|
627
493
|
return MILLENNIUM_API.callable((methodName, kwargs) => MILLENNIUM_API.__INTERNAL_CALL_WEBKIT_METHOD__(pluginName, methodName, kwargs), route.replace(/^webkit:/, ''));
|
|
628
494
|
}
|
|
629
495
|
return MILLENNIUM_API.callable(__call_server_method__, route);
|
|
630
496
|
}
|
|
631
|
-
|
|
632
|
-
return parts.join('\n');
|
|
633
|
-
};
|
|
634
|
-
function generate(code) {
|
|
635
|
-
/** Wrap it in a proxy */
|
|
497
|
+
function wrapEntryPoint(code) {
|
|
636
498
|
return `let PluginEntryPointMain = function() { ${code} return millennium_main; };`;
|
|
637
499
|
}
|
|
638
|
-
function
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
500
|
+
function insertMillennium(target, props) {
|
|
501
|
+
return {
|
|
502
|
+
name: '',
|
|
503
|
+
generateBundle(_, bundle) {
|
|
504
|
+
for (const fileName in bundle) {
|
|
505
|
+
const chunk = bundle[fileName];
|
|
506
|
+
if (chunk.type !== 'chunk')
|
|
507
|
+
continue;
|
|
508
|
+
let code = `\
|
|
509
|
+
const MILLENNIUM_IS_CLIENT_MODULE = ${target === BuildTarget.Plugin};
|
|
510
|
+
const pluginName = "${props.pluginName}";
|
|
511
|
+
${InitializePlugins.toString()}
|
|
512
|
+
${InitializePlugins.name}()
|
|
513
|
+
${kCallServerMethod}
|
|
514
|
+
${__wrapped_callable__.toString()}
|
|
515
|
+
${wrapEntryPoint(chunk.code)}
|
|
516
|
+
${ExecutePluginModule.toString()}
|
|
517
|
+
${ExecutePluginModule.name}()`;
|
|
518
|
+
if (props.minify) {
|
|
519
|
+
code = minify_sync(code).code ?? code;
|
|
520
|
+
}
|
|
521
|
+
chunk.code = code;
|
|
658
522
|
}
|
|
659
|
-
|
|
660
|
-
}
|
|
523
|
+
},
|
|
661
524
|
};
|
|
662
|
-
return { name: String(), generateBundle };
|
|
663
525
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
if (fs.existsSync('./ttc.config.mjs')) {
|
|
667
|
-
const { MillenniumCompilerPlugins } = await import(ttcConfigPath);
|
|
668
|
-
Logger.Info('millenniumAPI', 'Loading custom plugins from ttc.config.mjs... ' + chalk.green.bold('okay'));
|
|
669
|
-
return MillenniumCompilerPlugins;
|
|
670
|
-
}
|
|
671
|
-
return [];
|
|
526
|
+
function getFrontendDir(pluginJson) {
|
|
527
|
+
return pluginJson?.frontend ?? 'frontend';
|
|
672
528
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
// Filter out custom plugins that have the same name as input plugins
|
|
676
|
-
const filteredCustomPlugins = customPlugins.filter((customPlugin) => !plugins.some((plugin) => plugin.name === customPlugin.name));
|
|
677
|
-
// Merge input plugins with the filtered custom plugins
|
|
678
|
-
return [...plugins, ...filteredCustomPlugins];
|
|
529
|
+
function resolveEntryFile(frontendDir) {
|
|
530
|
+
return frontendDir === '.' || frontendDir === './' || frontendDir === '' ? './index.tsx' : `./${frontendDir}/index.tsx`;
|
|
679
531
|
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
}
|
|
686
|
-
else {
|
|
687
|
-
tsConfigPath = `./${frontendDir}/tsconfig.json`;
|
|
688
|
-
}
|
|
689
|
-
if (!fs.existsSync(tsConfigPath)) {
|
|
690
|
-
tsConfigPath = './tsconfig.json';
|
|
691
|
-
}
|
|
692
|
-
Logger.Info('millenniumAPI', 'Loading tsconfig from ' + chalk.cyan.bold(tsConfigPath) + '... ' + chalk.green.bold('okay'));
|
|
693
|
-
let pluginList = [
|
|
694
|
-
typescript({
|
|
695
|
-
tsconfig: tsConfigPath,
|
|
696
|
-
compilerOptions: {
|
|
697
|
-
outDir: undefined,
|
|
698
|
-
},
|
|
699
|
-
}),
|
|
700
|
-
url({
|
|
701
|
-
include: ['**/*.gif', '**/*.webm', '**/*.svg'], // Add all non-JS assets you use
|
|
702
|
-
limit: 0, // Set to 0 to always copy the file instead of inlining as base64
|
|
703
|
-
fileName: '[hash][extname]', // Optional: custom output naming
|
|
704
|
-
}),
|
|
705
|
-
InsertMillennium(ComponentType.Plugin, props),
|
|
706
|
-
nodeResolve({
|
|
707
|
-
browser: true,
|
|
708
|
-
}),
|
|
709
|
-
commonjs(),
|
|
710
|
-
nodePolyfills(),
|
|
711
|
-
scss({
|
|
712
|
-
output: false,
|
|
713
|
-
outputStyle: 'compressed',
|
|
714
|
-
sourceMap: false,
|
|
715
|
-
watch: 'src/styles',
|
|
716
|
-
sass: sass,
|
|
717
|
-
}),
|
|
718
|
-
json(),
|
|
719
|
-
constSysfsExpr(),
|
|
720
|
-
replace({
|
|
721
|
-
delimiters: ['', ''],
|
|
722
|
-
preventAssignment: true,
|
|
723
|
-
'process.env.NODE_ENV': JSON.stringify('production'),
|
|
724
|
-
'Millennium.callServerMethod': `__call_server_method__`,
|
|
725
|
-
'client.callable': `__wrapped_callable__`,
|
|
726
|
-
'client.pluginSelf': 'window.PLUGIN_LIST[pluginName]',
|
|
727
|
-
'client.Millennium.exposeObj(': 'client.Millennium.exposeObj(exports, ',
|
|
728
|
-
'client.BindPluginSettings()': 'client.BindPluginSettings(pluginName)',
|
|
729
|
-
}),
|
|
730
|
-
];
|
|
731
|
-
if (envVars.length > 0) {
|
|
732
|
-
pluginList.push(injectProcessEnv(envVars));
|
|
733
|
-
}
|
|
734
|
-
if (props.bTersePlugin) {
|
|
735
|
-
pluginList.push(terser());
|
|
736
|
-
}
|
|
737
|
-
return pluginList;
|
|
532
|
+
function resolveTsConfig(frontendDir) {
|
|
533
|
+
if (frontendDir === '.' || frontendDir === './')
|
|
534
|
+
return './tsconfig.json';
|
|
535
|
+
const candidate = `./${frontendDir}/tsconfig.json`;
|
|
536
|
+
return fs.existsSync(candidate) ? candidate : './tsconfig.json';
|
|
738
537
|
}
|
|
739
|
-
async function
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
include: ['**/*.mp4', '**/*.webm', '**/*.ogg'],
|
|
747
|
-
limit: 0, // do NOT inline
|
|
748
|
-
fileName: '[name][extname]',
|
|
749
|
-
destDir: 'dist/assets', // or adjust as needed
|
|
750
|
-
}),
|
|
751
|
-
resolve(),
|
|
752
|
-
commonjs(),
|
|
753
|
-
json(),
|
|
754
|
-
constSysfsExpr(),
|
|
755
|
-
replace({
|
|
756
|
-
delimiters: ['', ''],
|
|
757
|
-
preventAssignment: true,
|
|
758
|
-
'Millennium.callServerMethod': `__call_server_method__`,
|
|
759
|
-
'webkit.callable': `__wrapped_callable__`,
|
|
760
|
-
'webkit.Millennium.exposeObj(': 'webkit.Millennium.exposeObj(exports, ',
|
|
761
|
-
'client.BindPluginSettings()': 'client.BindPluginSettings(pluginName)',
|
|
762
|
-
}),
|
|
763
|
-
babel({
|
|
764
|
-
presets: ['@babel/preset-env', '@babel/preset-react'],
|
|
765
|
-
babelHelpers: 'bundled',
|
|
766
|
-
}),
|
|
767
|
-
];
|
|
768
|
-
if (envVars.length > 0) {
|
|
769
|
-
pluginList.push(injectProcessEnv(envVars));
|
|
770
|
-
}
|
|
771
|
-
pluginList = await MergePluginList(pluginList);
|
|
772
|
-
props.bTersePlugin && pluginList.push(terser());
|
|
773
|
-
return pluginList;
|
|
538
|
+
async function withUserPlugins(plugins) {
|
|
539
|
+
if (!fs.existsSync('./ttc.config.mjs'))
|
|
540
|
+
return plugins;
|
|
541
|
+
const configUrl = pathToFileURL(path.resolve('./ttc.config.mjs')).href;
|
|
542
|
+
const { MillenniumCompilerPlugins } = await import(configUrl);
|
|
543
|
+
const deduped = MillenniumCompilerPlugins.filter((custom) => !plugins.some((p) => p?.name === custom?.name));
|
|
544
|
+
return [...plugins, ...deduped];
|
|
774
545
|
}
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
546
|
+
function logLocation(log) {
|
|
547
|
+
const file = log.loc?.file ?? log.id;
|
|
548
|
+
if (!file || !log.loc)
|
|
549
|
+
return undefined;
|
|
550
|
+
return `${path.relative(process.cwd(), file)}:${log.loc.line}:${log.loc.column}`;
|
|
551
|
+
}
|
|
552
|
+
function stripPluginPrefix(message) {
|
|
553
|
+
message = message.replace(/^\[plugin [^\]]+\]\s*/, '');
|
|
554
|
+
message = message.replace(/^\S[^(]*\(\d+:\d+\):\s*/, '');
|
|
555
|
+
message = message.replace(/^@?[\w-]+\/[\w-]+\s+/, '');
|
|
556
|
+
return message;
|
|
557
|
+
}
|
|
558
|
+
class MillenniumBuild {
|
|
559
|
+
isExternal(id) {
|
|
560
|
+
const hint = this.forbidden.get(id);
|
|
561
|
+
if (hint) {
|
|
562
|
+
Logger.error(`${id} cannot be used here; ${hint}`);
|
|
563
|
+
process.exit(1);
|
|
564
|
+
}
|
|
565
|
+
return this.externals.has(id);
|
|
778
566
|
}
|
|
779
|
-
|
|
780
|
-
|
|
567
|
+
async build(input, sysfsPlugin, isMillennium) {
|
|
568
|
+
let hasErrors = false;
|
|
569
|
+
const config = {
|
|
570
|
+
input,
|
|
571
|
+
plugins: await this.plugins(sysfsPlugin),
|
|
572
|
+
onwarn: (warning) => {
|
|
573
|
+
const msg = stripPluginPrefix(warning.message);
|
|
574
|
+
const loc = logLocation(warning);
|
|
575
|
+
if (warning.plugin === 'typescript') {
|
|
576
|
+
Logger.error(msg, loc);
|
|
577
|
+
hasErrors = true;
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
Logger.warn(msg, loc);
|
|
581
|
+
}
|
|
582
|
+
},
|
|
583
|
+
context: 'window',
|
|
584
|
+
external: (id) => this.isExternal(id),
|
|
585
|
+
output: this.output(isMillennium),
|
|
586
|
+
};
|
|
587
|
+
await (await rollup(config)).write(config.output);
|
|
588
|
+
if (hasErrors)
|
|
589
|
+
process.exit(1);
|
|
781
590
|
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
entryFile = './index.tsx';
|
|
591
|
+
}
|
|
592
|
+
class FrontendBuild extends MillenniumBuild {
|
|
593
|
+
constructor(frontendDir, props) {
|
|
594
|
+
super();
|
|
595
|
+
this.frontendDir = frontendDir;
|
|
596
|
+
this.props = props;
|
|
597
|
+
this.externals = new Set(['@steambrew/client', 'react', 'react-dom', 'react-dom/client', 'react/jsx-runtime']);
|
|
598
|
+
this.forbidden = new Map([['@steambrew/webkit', 'use @steambrew/client in the frontend module']]);
|
|
791
599
|
}
|
|
792
|
-
|
|
793
|
-
|
|
600
|
+
plugins(sysfsPlugin) {
|
|
601
|
+
const tsPlugin = this.props.minify
|
|
602
|
+
? typescript({ tsconfig: resolveTsConfig(this.frontendDir), compilerOptions: { outDir: undefined } })
|
|
603
|
+
: esbuild({ tsconfig: resolveTsConfig(this.frontendDir) });
|
|
604
|
+
return [
|
|
605
|
+
tsPlugin,
|
|
606
|
+
url({ include: ['**/*.gif', '**/*.webm', '**/*.svg'], limit: 0, fileName: '[hash][extname]' }),
|
|
607
|
+
insertMillennium(BuildTarget.Plugin, this.props),
|
|
608
|
+
nodeResolve({ browser: true }),
|
|
609
|
+
commonjs(),
|
|
610
|
+
nodePolyfills(),
|
|
611
|
+
scss({ output: false, outputStyle: 'compressed', sourceMap: false, watch: 'src/styles', sass }),
|
|
612
|
+
json(),
|
|
613
|
+
sysfsPlugin,
|
|
614
|
+
replace({
|
|
615
|
+
delimiters: ['', ''],
|
|
616
|
+
preventAssignment: true,
|
|
617
|
+
'process.env.NODE_ENV': JSON.stringify('production'),
|
|
618
|
+
'Millennium.callServerMethod': '__call_server_method__',
|
|
619
|
+
'client.callable': '__wrapped_callable__',
|
|
620
|
+
'client.pluginSelf': 'window.PLUGIN_LIST[pluginName]',
|
|
621
|
+
'client.Millennium.exposeObj(': 'client.Millennium.exposeObj(exports, ',
|
|
622
|
+
'client.BindPluginSettings()': 'client.BindPluginSettings(pluginName)',
|
|
623
|
+
}),
|
|
624
|
+
...(Object.keys(env).length > 0 ? [injectProcessEnv(env)] : []),
|
|
625
|
+
...(this.props.minify ? [terser()] : []),
|
|
626
|
+
];
|
|
794
627
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
input: entryFile,
|
|
798
|
-
plugins: frontendPlugins,
|
|
799
|
-
context: 'window',
|
|
800
|
-
external: (id) => {
|
|
801
|
-
if (id === '@steambrew/webkit') {
|
|
802
|
-
Logger.Error('The @steambrew/webkit module should not be included in the frontend module, use @steambrew/client instead. Please remove it from the frontend module and try again.');
|
|
803
|
-
process.exit(1);
|
|
804
|
-
}
|
|
805
|
-
return id === '@steambrew/client' || id === 'react' || id === 'react-dom' || id === 'react-dom/client' || id === 'react/jsx-runtime';
|
|
806
|
-
},
|
|
807
|
-
output: {
|
|
628
|
+
output(isMillennium) {
|
|
629
|
+
return {
|
|
808
630
|
name: 'millennium_main',
|
|
809
|
-
file:
|
|
631
|
+
file: isMillennium ? '../../build/frontend.bin' : '.millennium/Dist/index.js',
|
|
810
632
|
globals: {
|
|
811
633
|
react: 'window.SP_REACT',
|
|
812
634
|
'react-dom': 'window.SP_REACTDOM',
|
|
@@ -816,38 +638,70 @@ const TranspilerPluginComponent = async (bIsMillennium, pluginJson, props) => {
|
|
|
816
638
|
},
|
|
817
639
|
exports: 'named',
|
|
818
640
|
format: 'iife',
|
|
819
|
-
}
|
|
820
|
-
}
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
class WebkitBuild extends MillenniumBuild {
|
|
645
|
+
constructor(props) {
|
|
646
|
+
super();
|
|
647
|
+
this.props = props;
|
|
648
|
+
this.externals = new Set(['@steambrew/webkit']);
|
|
649
|
+
this.forbidden = new Map([['@steambrew/client', 'use @steambrew/webkit in the webkit module']]);
|
|
650
|
+
}
|
|
651
|
+
async plugins(sysfsPlugin) {
|
|
652
|
+
const tsPlugin = this.props.minify
|
|
653
|
+
? typescript({ tsconfig: './webkit/tsconfig.json' })
|
|
654
|
+
: esbuild({ tsconfig: './webkit/tsconfig.json' });
|
|
655
|
+
const base = [
|
|
656
|
+
insertMillennium(BuildTarget.Webkit, this.props),
|
|
657
|
+
tsPlugin,
|
|
658
|
+
url({ include: ['**/*.mp4', '**/*.webm', '**/*.ogg'], limit: 0, fileName: '[name][extname]', destDir: 'dist/assets' }),
|
|
659
|
+
resolve(),
|
|
660
|
+
commonjs(),
|
|
661
|
+
json(),
|
|
662
|
+
sysfsPlugin,
|
|
663
|
+
replace({
|
|
664
|
+
delimiters: ['', ''],
|
|
665
|
+
preventAssignment: true,
|
|
666
|
+
'Millennium.callServerMethod': '__call_server_method__',
|
|
667
|
+
'webkit.callable': '__wrapped_callable__',
|
|
668
|
+
'webkit.Millennium.exposeObj(': 'webkit.Millennium.exposeObj(exports, ',
|
|
669
|
+
'client.BindPluginSettings()': 'client.BindPluginSettings(pluginName)',
|
|
670
|
+
}),
|
|
671
|
+
babel({ presets: ['@babel/preset-env', '@babel/preset-react'], babelHelpers: 'bundled' }),
|
|
672
|
+
...(Object.keys(env).length > 0 ? [injectProcessEnv(env)] : []),
|
|
673
|
+
];
|
|
674
|
+
const merged = await withUserPlugins(base);
|
|
675
|
+
return this.props.minify ? [...merged, terser()] : merged;
|
|
676
|
+
}
|
|
677
|
+
output(_isMillennium) {
|
|
678
|
+
return {
|
|
679
|
+
name: 'millennium_main',
|
|
680
|
+
file: '.millennium/Dist/webkit.js',
|
|
681
|
+
exports: 'named',
|
|
682
|
+
format: 'iife',
|
|
683
|
+
globals: { '@steambrew/webkit': 'window.MILLENNIUM_API' },
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
const TranspilerPluginComponent = async (isMillennium, pluginJson, props) => {
|
|
688
|
+
const webkitDir = './webkit/index.tsx';
|
|
689
|
+
const frontendDir = getFrontendDir(pluginJson);
|
|
690
|
+
const sysfs = constSysfsExpr();
|
|
821
691
|
try {
|
|
822
|
-
await (
|
|
823
|
-
if (fs.existsSync(
|
|
824
|
-
|
|
825
|
-
input: `./webkit/index.tsx`,
|
|
826
|
-
plugins: await GetWebkitPluginComponents(props),
|
|
827
|
-
context: 'window',
|
|
828
|
-
external: (id) => {
|
|
829
|
-
if (id === '@steambrew/client') {
|
|
830
|
-
Logger.Error('The @steambrew/client module should not be included in the webkit module, use @steambrew/webkit instead. Please remove it from the webkit module and try again.');
|
|
831
|
-
process.exit(1);
|
|
832
|
-
}
|
|
833
|
-
return id === '@steambrew/webkit';
|
|
834
|
-
},
|
|
835
|
-
output: {
|
|
836
|
-
name: 'millennium_main',
|
|
837
|
-
file: '.millennium/Dist/webkit.js',
|
|
838
|
-
exports: 'named',
|
|
839
|
-
format: 'iife',
|
|
840
|
-
globals: {
|
|
841
|
-
'@steambrew/webkit': 'window.MILLENNIUM_API',
|
|
842
|
-
},
|
|
843
|
-
},
|
|
844
|
-
};
|
|
845
|
-
await (await rollup(webkitRollupConfig)).write(webkitRollupConfig.output);
|
|
692
|
+
await new FrontendBuild(frontendDir, props).build(resolveEntryFile(frontendDir), sysfs.plugin, isMillennium);
|
|
693
|
+
if (fs.existsSync(webkitDir)) {
|
|
694
|
+
await new WebkitBuild(props).build(webkitDir, sysfs.plugin, isMillennium);
|
|
846
695
|
}
|
|
847
|
-
Logger.
|
|
696
|
+
Logger.done({
|
|
697
|
+
elapsedMs: performance.now() - global.PerfStartTime,
|
|
698
|
+
buildType: props.minify ? 'prod' : 'dev',
|
|
699
|
+
sysfsCount: sysfs.getCount() || undefined,
|
|
700
|
+
envCount: Object.keys(env).length || undefined,
|
|
701
|
+
});
|
|
848
702
|
}
|
|
849
703
|
catch (exception) {
|
|
850
|
-
Logger.
|
|
704
|
+
Logger.error(stripPluginPrefix(exception?.message ?? String(exception)), logLocation(exception));
|
|
851
705
|
process.exit(1);
|
|
852
706
|
}
|
|
853
707
|
};
|
|
@@ -864,18 +718,14 @@ const StartCompilerModule = () => {
|
|
|
864
718
|
const parameters = ValidateParameters(process.argv.slice(2));
|
|
865
719
|
const bIsMillennium = parameters.isMillennium || false;
|
|
866
720
|
const bTersePlugin = parameters.type == BuildType.ProdBuild;
|
|
867
|
-
console.log(chalk.greenBright.bold('config'), 'Building target:', parameters.targetPlugin, 'with type:', BuildType[parameters.type], 'minify:', bTersePlugin, '...');
|
|
868
721
|
ValidatePlugin(bIsMillennium, parameters.targetPlugin)
|
|
869
722
|
.then((json) => {
|
|
870
723
|
const props = {
|
|
871
|
-
|
|
872
|
-
|
|
724
|
+
minify: bTersePlugin,
|
|
725
|
+
pluginName: json?.name,
|
|
873
726
|
};
|
|
874
727
|
TranspilerPluginComponent(bIsMillennium, json, props);
|
|
875
728
|
})
|
|
876
|
-
/**
|
|
877
|
-
* plugin is invalid, we close the proccess as it has already been handled
|
|
878
|
-
*/
|
|
879
729
|
.catch(() => {
|
|
880
730
|
process.exit();
|
|
881
731
|
});
|