@steambrew/ttc 2.8.7 → 3.0.1
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/.claude/settings.local.json +9 -0
- package/.prettierrc +9 -9
- package/bun.lock +611 -0
- package/dist/index.js +305 -460
- package/package.json +54 -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 +298 -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';
|
|
@@ -12,8 +12,8 @@ import replace from '@rollup/plugin-replace';
|
|
|
12
12
|
import terser from '@rollup/plugin-terser';
|
|
13
13
|
import typescript from '@rollup/plugin-typescript';
|
|
14
14
|
import url from '@rollup/plugin-url';
|
|
15
|
-
import { rollup } from 'rollup';
|
|
16
15
|
import nodePolyfills from 'rollup-plugin-polyfill-node';
|
|
16
|
+
import { rollup } from 'rollup';
|
|
17
17
|
import { minify_sync } from 'terser';
|
|
18
18
|
import scss from 'rollup-plugin-scss';
|
|
19
19
|
import * as sass from 'sass';
|
|
@@ -26,57 +26,53 @@ import MagicString from 'magic-string';
|
|
|
26
26
|
import _traverse from '@babel/traverse';
|
|
27
27
|
import { performance as performance$1 } from 'perf_hooks';
|
|
28
28
|
|
|
29
|
+
const version = JSON.parse(readFileSync(path.resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'), 'utf8')).version;
|
|
29
30
|
const Logger = {
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
warn(message, loc) {
|
|
32
|
+
if (loc) {
|
|
33
|
+
console.warn(`${chalk.dim(loc + ':')} ${message}`);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.warn(`${chalk.yellow('warning:')} ${message}`);
|
|
37
|
+
}
|
|
32
38
|
},
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
error(message, loc) {
|
|
40
|
+
if (loc) {
|
|
41
|
+
console.error(`${chalk.red(loc + ':')} ${message}`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.error(`${chalk.red('error:')} ${message}`);
|
|
45
|
+
}
|
|
35
46
|
},
|
|
36
|
-
|
|
37
|
-
console.
|
|
47
|
+
update(current, latest, installCmd) {
|
|
48
|
+
console.log(`\n${chalk.yellow('update available')} ${chalk.dim(current)} → ${chalk.green(latest)}`);
|
|
49
|
+
console.log(`${chalk.dim('run:')} ${installCmd}\n`);
|
|
38
50
|
},
|
|
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
|
-
}
|
|
51
|
+
done({ elapsedMs, buildType, sysfsCount, envCount }) {
|
|
52
|
+
const elapsed = `${(elapsedMs / 1000).toFixed(2)}s`;
|
|
53
|
+
const meta = [`ttc v${version}`];
|
|
54
|
+
if (buildType === 'dev')
|
|
55
|
+
meta.push('no type checking');
|
|
56
|
+
if (sysfsCount)
|
|
57
|
+
meta.push(`${sysfsCount} constSysfsExpr`);
|
|
58
|
+
if (envCount)
|
|
59
|
+
meta.push(`${envCount} env var${envCount > 1 ? 's' : ''}`);
|
|
60
|
+
console.log(`${chalk.green('Finished')} ${buildType} in ${elapsed} ` + chalk.dim('(' + meta.join(', ') + ')'));
|
|
61
61
|
},
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
/***
|
|
65
|
-
* @brief print the parameter list to the stdout
|
|
66
|
-
*/
|
|
67
64
|
const PrintParamHelp = () => {
|
|
68
|
-
console.log(
|
|
69
|
-
'
|
|
70
|
-
|
|
71
|
-
'
|
|
72
|
-
'
|
|
73
|
-
|
|
74
|
-
': '
|
|
75
|
-
|
|
76
|
-
'
|
|
77
|
-
'
|
|
78
|
-
|
|
79
|
-
': path to plugin, default to cwd');
|
|
65
|
+
console.log([
|
|
66
|
+
'',
|
|
67
|
+
'usage: millennium-ttc --build <dev|prod> [options]',
|
|
68
|
+
'',
|
|
69
|
+
'options:',
|
|
70
|
+
' --build <dev|prod> build type (prod enables minification)',
|
|
71
|
+
' --target <path> plugin directory (default: current directory)',
|
|
72
|
+
' --no-update skip update check',
|
|
73
|
+
' --help show this message',
|
|
74
|
+
'',
|
|
75
|
+
].join('\n'));
|
|
80
76
|
};
|
|
81
77
|
var BuildType;
|
|
82
78
|
(function (BuildType) {
|
|
@@ -89,9 +85,8 @@ const ValidateParameters = (args) => {
|
|
|
89
85
|
PrintParamHelp();
|
|
90
86
|
process.exit();
|
|
91
87
|
}
|
|
92
|
-
// startup args are invalid
|
|
93
88
|
if (!args.includes('--build')) {
|
|
94
|
-
Logger.
|
|
89
|
+
Logger.error('missing required argument: --build');
|
|
95
90
|
PrintParamHelp();
|
|
96
91
|
process.exit();
|
|
97
92
|
}
|
|
@@ -106,14 +101,14 @@ const ValidateParameters = (args) => {
|
|
|
106
101
|
typeProp = BuildType.ProdBuild;
|
|
107
102
|
break;
|
|
108
103
|
default: {
|
|
109
|
-
Logger.
|
|
104
|
+
Logger.error('--build must be one of: dev, prod');
|
|
110
105
|
process.exit();
|
|
111
106
|
}
|
|
112
107
|
}
|
|
113
108
|
}
|
|
114
109
|
if (args[i] == '--target') {
|
|
115
110
|
if (args[i + 1] === undefined) {
|
|
116
|
-
Logger.
|
|
111
|
+
Logger.error('--target requires a path argument');
|
|
117
112
|
process.exit();
|
|
118
113
|
}
|
|
119
114
|
targetProp = args[i + 1];
|
|
@@ -129,40 +124,61 @@ const ValidateParameters = (args) => {
|
|
|
129
124
|
};
|
|
130
125
|
};
|
|
131
126
|
|
|
127
|
+
async function fileExists(filePath) {
|
|
128
|
+
return access(filePath).then(() => true).catch(() => false);
|
|
129
|
+
}
|
|
130
|
+
async function detectPackageManager() {
|
|
131
|
+
const userAgent = process.env.npm_config_user_agent ?? '';
|
|
132
|
+
if (userAgent.startsWith('bun'))
|
|
133
|
+
return 'bun';
|
|
134
|
+
if (userAgent.startsWith('pnpm'))
|
|
135
|
+
return 'pnpm';
|
|
136
|
+
if (userAgent.startsWith('yarn'))
|
|
137
|
+
return 'yarn';
|
|
138
|
+
const cwd = process.cwd();
|
|
139
|
+
if (await fileExists(path.join(cwd, 'bun.lock')) || await fileExists(path.join(cwd, 'bun.lockb')))
|
|
140
|
+
return 'bun';
|
|
141
|
+
if (await fileExists(path.join(cwd, 'pnpm-lock.yaml')))
|
|
142
|
+
return 'pnpm';
|
|
143
|
+
if (await fileExists(path.join(cwd, 'yarn.lock')))
|
|
144
|
+
return 'yarn';
|
|
145
|
+
return 'npm';
|
|
146
|
+
}
|
|
147
|
+
function installCommand(pm, pkg) {
|
|
148
|
+
switch (pm) {
|
|
149
|
+
case 'bun': return `bun add -d ${pkg}`;
|
|
150
|
+
case 'pnpm': return `pnpm add -D ${pkg}`;
|
|
151
|
+
case 'yarn': return `yarn add -D ${pkg}`;
|
|
152
|
+
default: return `npm i -D ${pkg}`;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
132
155
|
const CheckForUpdates = async () => {
|
|
133
|
-
|
|
156
|
+
try {
|
|
134
157
|
const packageJsonPath = path.resolve(dirname(fileURLToPath(import.meta.url)), '../package.json');
|
|
135
158
|
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
|
-
});
|
|
159
|
+
const response = await fetch('https://registry.npmjs.org/@steambrew/ttc');
|
|
160
|
+
const json = await response.json();
|
|
161
|
+
const latest = json?.['dist-tags']?.latest;
|
|
162
|
+
if (latest && latest !== packageJson.version) {
|
|
163
|
+
const pm = await detectPackageManager();
|
|
164
|
+
Logger.update(packageJson.version, latest, installCommand(pm, `@steambrew/ttc@${latest}`));
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// network or parse failure — silently skip
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
155
172
|
};
|
|
156
173
|
|
|
157
174
|
const ValidatePlugin = (bIsMillennium, target) => {
|
|
158
175
|
return new Promise((resolve, reject) => {
|
|
159
176
|
if (!existsSync(target)) {
|
|
160
|
-
|
|
177
|
+
Logger.error(`target path does not exist: ${target}`);
|
|
161
178
|
reject();
|
|
162
179
|
return;
|
|
163
180
|
}
|
|
164
181
|
if (bIsMillennium) {
|
|
165
|
-
console.log(chalk.green.bold('\n[+] Using Millennium internal build configuration'));
|
|
166
182
|
resolve({
|
|
167
183
|
name: 'core',
|
|
168
184
|
common_name: 'Millennium',
|
|
@@ -174,27 +190,28 @@ const ValidatePlugin = (bIsMillennium, target) => {
|
|
|
174
190
|
}
|
|
175
191
|
const pluginModule = path.join(target, 'plugin.json');
|
|
176
192
|
if (!existsSync(pluginModule)) {
|
|
177
|
-
|
|
193
|
+
Logger.error(`plugin.json not found: ${pluginModule}`);
|
|
178
194
|
reject();
|
|
179
195
|
return;
|
|
180
196
|
}
|
|
181
197
|
readFile$1(pluginModule, 'utf8', (err, data) => {
|
|
182
198
|
if (err) {
|
|
183
|
-
|
|
199
|
+
Logger.error(`could not read plugin.json: ${pluginModule}`);
|
|
184
200
|
reject();
|
|
185
201
|
return;
|
|
186
202
|
}
|
|
187
203
|
try {
|
|
188
|
-
|
|
189
|
-
|
|
204
|
+
const parsed = JSON.parse(data);
|
|
205
|
+
if (!('name' in parsed)) {
|
|
206
|
+
Logger.error('plugin.json is missing required "name" field');
|
|
190
207
|
reject();
|
|
191
208
|
}
|
|
192
209
|
else {
|
|
193
|
-
resolve(
|
|
210
|
+
resolve(parsed);
|
|
194
211
|
}
|
|
195
212
|
}
|
|
196
213
|
catch (parseError) {
|
|
197
|
-
|
|
214
|
+
Logger.error('plugin.json contains invalid JSON:', pluginModule);
|
|
198
215
|
reject();
|
|
199
216
|
}
|
|
200
217
|
});
|
|
@@ -205,178 +222,42 @@ const ValidatePlugin = (bIsMillennium, target) => {
|
|
|
205
222
|
* @description Append the active plugin to the global plugin
|
|
206
223
|
* list and notify that the frontend Loaded.
|
|
207
224
|
*/
|
|
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
|
-
}
|
|
225
|
+
async function ExecutePluginModule() {
|
|
226
|
+
let PluginModule = PluginEntryPointMain();
|
|
227
|
+
/** Assign the plugin on plugin list. */
|
|
228
|
+
Object.assign(window.PLUGIN_LIST[pluginName], {
|
|
229
|
+
...PluginModule,
|
|
230
|
+
__millennium_internal_plugin_name_do_not_use_or_change__: pluginName,
|
|
254
231
|
});
|
|
232
|
+
/** Run the rolled up plugins default exported function */
|
|
233
|
+
let pluginProps = await PluginModule.default();
|
|
234
|
+
function isValidSidebarNavComponent(obj) {
|
|
235
|
+
return obj && obj.title !== undefined && obj.icon !== undefined && obj.content !== undefined;
|
|
236
|
+
}
|
|
237
|
+
if (pluginProps && isValidSidebarNavComponent(pluginProps)) {
|
|
238
|
+
window.MILLENNIUM_SIDEBAR_NAVIGATION_PANELS[pluginName] = pluginProps;
|
|
239
|
+
}
|
|
240
|
+
/** If the current module is a client module, post message id=1 which calls the front_end_loaded method on the backend. */
|
|
241
|
+
if (MILLENNIUM_IS_CLIENT_MODULE) {
|
|
242
|
+
MILLENNIUM_BACKEND_IPC.postMessage(1, { pluginName: pluginName });
|
|
243
|
+
}
|
|
255
244
|
}
|
|
256
245
|
/**
|
|
257
246
|
* @description Initialize the plugins settings store and the plugin list.
|
|
258
247
|
* This function is called once per plugin and is used to store the plugin settings and the plugin list.
|
|
259
248
|
*/
|
|
260
249
|
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
|
-
*/
|
|
250
|
+
var _a;
|
|
266
251
|
(_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
252
|
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
253
|
}
|
|
371
254
|
|
|
372
255
|
const traverse = _traverse.default;
|
|
373
|
-
const Log = (...message) => {
|
|
374
|
-
console.log(chalk.blueBright.bold('constSysfsExpr'), ...message);
|
|
375
|
-
};
|
|
376
256
|
function constSysfsExpr(options = {}) {
|
|
377
257
|
const filter = createFilter(options.include, options.exclude);
|
|
378
258
|
const pluginName = 'millennium-const-sysfs-expr';
|
|
379
|
-
|
|
259
|
+
let count = 0;
|
|
260
|
+
const plugin = {
|
|
380
261
|
name: pluginName,
|
|
381
262
|
transform(code, id) {
|
|
382
263
|
if (!filter(id))
|
|
@@ -512,7 +393,6 @@ function constSysfsExpr(options = {}) {
|
|
|
512
393
|
return;
|
|
513
394
|
}
|
|
514
395
|
try {
|
|
515
|
-
const currentLocString = node.loc?.start ? ` at ${id}:${node.loc.start.line}:${node.loc.start.column}` : ` in ${id}`;
|
|
516
396
|
const searchBasePath = callOptions.basePath
|
|
517
397
|
? path.isAbsolute(callOptions.basePath)
|
|
518
398
|
? callOptions.basePath
|
|
@@ -521,13 +401,11 @@ function constSysfsExpr(options = {}) {
|
|
|
521
401
|
? path.dirname(pathOrPattern)
|
|
522
402
|
: path.resolve(path.dirname(id), path.dirname(pathOrPattern));
|
|
523
403
|
let embeddedContent;
|
|
524
|
-
let embeddedCount = 0;
|
|
525
404
|
const isPotentialPattern = /[?*+!@()[\]{}]/.test(pathOrPattern);
|
|
526
405
|
if (!isPotentialPattern &&
|
|
527
406
|
fs.existsSync(path.resolve(searchBasePath, pathOrPattern)) &&
|
|
528
407
|
fs.statSync(path.resolve(searchBasePath, pathOrPattern)).isFile()) {
|
|
529
408
|
const singleFilePath = path.resolve(searchBasePath, pathOrPattern);
|
|
530
|
-
Log(`Mode: Single file (first argument "${pathOrPattern}" resolved to "${singleFilePath}" relative to "${searchBasePath}")`);
|
|
531
409
|
try {
|
|
532
410
|
const rawContent = fs.readFileSync(singleFilePath, callOptions.encoding);
|
|
533
411
|
const contentString = rawContent.toString();
|
|
@@ -537,8 +415,6 @@ function constSysfsExpr(options = {}) {
|
|
|
537
415
|
fileName: path.relative(searchBasePath, singleFilePath),
|
|
538
416
|
};
|
|
539
417
|
embeddedContent = JSON.stringify(fileInfo);
|
|
540
|
-
embeddedCount = 1;
|
|
541
|
-
Log(`Embedded 1 specific file for call${currentLocString}`);
|
|
542
418
|
}
|
|
543
419
|
catch (fileError) {
|
|
544
420
|
let message = String(fileError instanceof Error ? fileError.message : fileError ?? 'Unknown file read error');
|
|
@@ -547,8 +423,6 @@ function constSysfsExpr(options = {}) {
|
|
|
547
423
|
}
|
|
548
424
|
}
|
|
549
425
|
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
426
|
const matchingFiles = glob.sync(pathOrPattern, {
|
|
553
427
|
cwd: searchBasePath,
|
|
554
428
|
nodir: true,
|
|
@@ -571,15 +445,13 @@ function constSysfsExpr(options = {}) {
|
|
|
571
445
|
}
|
|
572
446
|
}
|
|
573
447
|
embeddedContent = JSON.stringify(fileInfoArray);
|
|
574
|
-
embeddedCount = fileInfoArray.length;
|
|
575
|
-
Log(`Embedded ${embeddedCount} file(s) matching pattern for call${currentLocString}`);
|
|
576
448
|
}
|
|
577
449
|
// Replace the call expression with the generated content string
|
|
578
450
|
magicString.overwrite(node.start, node.end, embeddedContent);
|
|
579
451
|
hasReplaced = true;
|
|
452
|
+
count++;
|
|
580
453
|
}
|
|
581
454
|
catch (error) {
|
|
582
|
-
console.error(`Failed to process files for constSysfsExpr call in ${id}:`, error);
|
|
583
455
|
const message = String(error instanceof Error ? error.message : error ?? 'Unknown error during file processing');
|
|
584
456
|
this.error(`Could not process files for constSysfsExpr: ${message}`, node.loc?.start.index);
|
|
585
457
|
return;
|
|
@@ -589,7 +461,6 @@ function constSysfsExpr(options = {}) {
|
|
|
589
461
|
});
|
|
590
462
|
}
|
|
591
463
|
catch (error) {
|
|
592
|
-
console.error(`Error parsing or traversing ${id}:`, error);
|
|
593
464
|
const message = String(error instanceof Error ? error.message : error ?? 'Unknown parsing error');
|
|
594
465
|
this.error(`Failed to parse ${id}: ${message}`);
|
|
595
466
|
return null;
|
|
@@ -606,207 +477,155 @@ function constSysfsExpr(options = {}) {
|
|
|
606
477
|
return result;
|
|
607
478
|
},
|
|
608
479
|
};
|
|
480
|
+
return { plugin, getCount: () => count };
|
|
609
481
|
}
|
|
610
482
|
|
|
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)';
|
|
483
|
+
const env = dotenv.config().parsed ?? {};
|
|
484
|
+
var BuildTarget;
|
|
485
|
+
(function (BuildTarget) {
|
|
486
|
+
BuildTarget[BuildTarget["Plugin"] = 0] = "Plugin";
|
|
487
|
+
BuildTarget[BuildTarget["Webkit"] = 1] = "Webkit";
|
|
488
|
+
})(BuildTarget || (BuildTarget = {}));
|
|
489
|
+
const kCallServerMethod = 'const __call_server_method__ = (methodName, kwargs) => Millennium.callServerMethod(pluginName, methodName, kwargs)';
|
|
625
490
|
function __wrapped_callable__(route) {
|
|
626
491
|
if (route.startsWith('webkit:')) {
|
|
627
492
|
return MILLENNIUM_API.callable((methodName, kwargs) => MILLENNIUM_API.__INTERNAL_CALL_WEBKIT_METHOD__(pluginName, methodName, kwargs), route.replace(/^webkit:/, ''));
|
|
628
493
|
}
|
|
629
494
|
return MILLENNIUM_API.callable(__call_server_method__, route);
|
|
630
495
|
}
|
|
631
|
-
|
|
632
|
-
return parts.join('\n');
|
|
633
|
-
};
|
|
634
|
-
function generate(code) {
|
|
635
|
-
/** Wrap it in a proxy */
|
|
496
|
+
function wrapEntryPoint(code) {
|
|
636
497
|
return `let PluginEntryPointMain = function() { ${code} return millennium_main; };`;
|
|
637
498
|
}
|
|
638
|
-
function
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
499
|
+
function insertMillennium(target, props) {
|
|
500
|
+
return {
|
|
501
|
+
name: '',
|
|
502
|
+
generateBundle(_, bundle) {
|
|
503
|
+
for (const fileName in bundle) {
|
|
504
|
+
const chunk = bundle[fileName];
|
|
505
|
+
if (chunk.type !== 'chunk')
|
|
506
|
+
continue;
|
|
507
|
+
let code = `\
|
|
508
|
+
const MILLENNIUM_IS_CLIENT_MODULE = ${target === BuildTarget.Plugin};
|
|
509
|
+
const pluginName = "${props.pluginName}";
|
|
510
|
+
${InitializePlugins.toString()}
|
|
511
|
+
${InitializePlugins.name}()
|
|
512
|
+
${kCallServerMethod}
|
|
513
|
+
${__wrapped_callable__.toString()}
|
|
514
|
+
${wrapEntryPoint(chunk.code)}
|
|
515
|
+
${ExecutePluginModule.toString()}
|
|
516
|
+
${ExecutePluginModule.name}()`;
|
|
517
|
+
if (props.minify) {
|
|
518
|
+
code = minify_sync(code).code ?? code;
|
|
519
|
+
}
|
|
520
|
+
chunk.code = code;
|
|
658
521
|
}
|
|
659
|
-
|
|
660
|
-
}
|
|
522
|
+
},
|
|
661
523
|
};
|
|
662
|
-
return { name: String(), generateBundle };
|
|
663
524
|
}
|
|
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 [];
|
|
525
|
+
function getFrontendDir(pluginJson) {
|
|
526
|
+
return pluginJson?.frontend ?? 'frontend';
|
|
672
527
|
}
|
|
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];
|
|
528
|
+
function resolveEntryFile(frontendDir) {
|
|
529
|
+
return frontendDir === '.' || frontendDir === './' || frontendDir === '' ? './index.tsx' : `./${frontendDir}/index.tsx`;
|
|
679
530
|
}
|
|
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;
|
|
531
|
+
function resolveTsConfig(frontendDir) {
|
|
532
|
+
if (frontendDir === '.' || frontendDir === './')
|
|
533
|
+
return './tsconfig.json';
|
|
534
|
+
const candidate = `./${frontendDir}/tsconfig.json`;
|
|
535
|
+
return fs.existsSync(candidate) ? candidate : './tsconfig.json';
|
|
738
536
|
}
|
|
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;
|
|
537
|
+
async function withUserPlugins(plugins) {
|
|
538
|
+
if (!fs.existsSync('./ttc.config.mjs'))
|
|
539
|
+
return plugins;
|
|
540
|
+
const configUrl = pathToFileURL(path.resolve('./ttc.config.mjs')).href;
|
|
541
|
+
const { MillenniumCompilerPlugins } = await import(configUrl);
|
|
542
|
+
const deduped = MillenniumCompilerPlugins.filter((custom) => !plugins.some((p) => p?.name === custom?.name));
|
|
543
|
+
return [...plugins, ...deduped];
|
|
774
544
|
}
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
545
|
+
function logLocation(log) {
|
|
546
|
+
const file = log.loc?.file ?? log.id;
|
|
547
|
+
if (!file || !log.loc)
|
|
548
|
+
return undefined;
|
|
549
|
+
return `${path.relative(process.cwd(), file)}:${log.loc.line}:${log.loc.column}`;
|
|
550
|
+
}
|
|
551
|
+
function stripPluginPrefix(message) {
|
|
552
|
+
message = message.replace(/^\[plugin [^\]]+\]\s*/, '');
|
|
553
|
+
message = message.replace(/^\S[^(]*\(\d+:\d+\):\s*/, '');
|
|
554
|
+
message = message.replace(/^@?[\w-]+\/[\w-]+\s+/, '');
|
|
555
|
+
return message;
|
|
556
|
+
}
|
|
557
|
+
class MillenniumBuild {
|
|
558
|
+
isExternal(id) {
|
|
559
|
+
const hint = this.forbidden.get(id);
|
|
560
|
+
if (hint) {
|
|
561
|
+
Logger.error(`${id} cannot be used here; ${hint}`);
|
|
562
|
+
process.exit(1);
|
|
563
|
+
}
|
|
564
|
+
return this.externals.has(id);
|
|
778
565
|
}
|
|
779
|
-
|
|
780
|
-
|
|
566
|
+
async build(input, sysfsPlugin, isMillennium) {
|
|
567
|
+
let hasErrors = false;
|
|
568
|
+
const config = {
|
|
569
|
+
input,
|
|
570
|
+
plugins: await this.plugins(sysfsPlugin),
|
|
571
|
+
onwarn: (warning) => {
|
|
572
|
+
const msg = stripPluginPrefix(warning.message);
|
|
573
|
+
const loc = logLocation(warning);
|
|
574
|
+
if (warning.plugin === 'typescript') {
|
|
575
|
+
Logger.error(msg, loc);
|
|
576
|
+
hasErrors = true;
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
Logger.warn(msg, loc);
|
|
580
|
+
}
|
|
581
|
+
},
|
|
582
|
+
context: 'window',
|
|
583
|
+
external: (id) => this.isExternal(id),
|
|
584
|
+
output: this.output(isMillennium),
|
|
585
|
+
};
|
|
586
|
+
await (await rollup(config)).write(config.output);
|
|
587
|
+
if (hasErrors)
|
|
588
|
+
process.exit(1);
|
|
781
589
|
}
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
entryFile = './index.tsx';
|
|
590
|
+
}
|
|
591
|
+
class FrontendBuild extends MillenniumBuild {
|
|
592
|
+
constructor(frontendDir, props) {
|
|
593
|
+
super();
|
|
594
|
+
this.frontendDir = frontendDir;
|
|
595
|
+
this.props = props;
|
|
596
|
+
this.externals = new Set(['@steambrew/client', 'react', 'react-dom', 'react-dom/client', 'react/jsx-runtime']);
|
|
597
|
+
this.forbidden = new Map([['@steambrew/webkit', 'use @steambrew/client in the frontend module']]);
|
|
791
598
|
}
|
|
792
|
-
|
|
793
|
-
|
|
599
|
+
plugins(sysfsPlugin) {
|
|
600
|
+
const tsPlugin = typescript({ tsconfig: resolveTsConfig(this.frontendDir), compilerOptions: { noCheck: !this.props.minify, outDir: undefined } });
|
|
601
|
+
return [
|
|
602
|
+
tsPlugin,
|
|
603
|
+
url({ include: ['**/*.gif', '**/*.webm', '**/*.svg'], limit: 0, fileName: '[hash][extname]' }),
|
|
604
|
+
insertMillennium(BuildTarget.Plugin, this.props),
|
|
605
|
+
nodeResolve({ browser: true }),
|
|
606
|
+
commonjs(),
|
|
607
|
+
nodePolyfills(),
|
|
608
|
+
scss({ output: false, outputStyle: 'compressed', sourceMap: false, watch: 'src/styles', sass }),
|
|
609
|
+
json(),
|
|
610
|
+
sysfsPlugin,
|
|
611
|
+
replace({
|
|
612
|
+
delimiters: ['', ''],
|
|
613
|
+
preventAssignment: true,
|
|
614
|
+
'process.env.NODE_ENV': JSON.stringify('production'),
|
|
615
|
+
'Millennium.callServerMethod': '__call_server_method__',
|
|
616
|
+
'client.callable': '__wrapped_callable__',
|
|
617
|
+
'client.pluginSelf': 'window.PLUGIN_LIST[pluginName]',
|
|
618
|
+
'client.Millennium.exposeObj(': 'client.Millennium.exposeObj(exports, ',
|
|
619
|
+
'client.BindPluginSettings()': 'client.BindPluginSettings(pluginName)',
|
|
620
|
+
}),
|
|
621
|
+
...(Object.keys(env).length > 0 ? [injectProcessEnv(env)] : []),
|
|
622
|
+
...(this.props.minify ? [terser()] : []),
|
|
623
|
+
];
|
|
794
624
|
}
|
|
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: {
|
|
625
|
+
output(isMillennium) {
|
|
626
|
+
return {
|
|
808
627
|
name: 'millennium_main',
|
|
809
|
-
file:
|
|
628
|
+
file: isMillennium ? '../../build/frontend.bin' : '.millennium/Dist/index.js',
|
|
810
629
|
globals: {
|
|
811
630
|
react: 'window.SP_REACT',
|
|
812
631
|
'react-dom': 'window.SP_REACTDOM',
|
|
@@ -816,38 +635,68 @@ const TranspilerPluginComponent = async (bIsMillennium, pluginJson, props) => {
|
|
|
816
635
|
},
|
|
817
636
|
exports: 'named',
|
|
818
637
|
format: 'iife',
|
|
819
|
-
}
|
|
820
|
-
}
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
class WebkitBuild extends MillenniumBuild {
|
|
642
|
+
constructor(props) {
|
|
643
|
+
super();
|
|
644
|
+
this.props = props;
|
|
645
|
+
this.externals = new Set(['@steambrew/webkit']);
|
|
646
|
+
this.forbidden = new Map([['@steambrew/client', 'use @steambrew/webkit in the webkit module']]);
|
|
647
|
+
}
|
|
648
|
+
async plugins(sysfsPlugin) {
|
|
649
|
+
const tsPlugin = typescript({ tsconfig: './webkit/tsconfig.json', compilerOptions: { noCheck: !this.props.minify } });
|
|
650
|
+
const base = [
|
|
651
|
+
insertMillennium(BuildTarget.Webkit, this.props),
|
|
652
|
+
tsPlugin,
|
|
653
|
+
url({ include: ['**/*.mp4', '**/*.webm', '**/*.ogg'], limit: 0, fileName: '[name][extname]', destDir: 'dist/assets' }),
|
|
654
|
+
resolve(),
|
|
655
|
+
commonjs(),
|
|
656
|
+
json(),
|
|
657
|
+
sysfsPlugin,
|
|
658
|
+
replace({
|
|
659
|
+
delimiters: ['', ''],
|
|
660
|
+
preventAssignment: true,
|
|
661
|
+
'Millennium.callServerMethod': '__call_server_method__',
|
|
662
|
+
'webkit.callable': '__wrapped_callable__',
|
|
663
|
+
'webkit.Millennium.exposeObj(': 'webkit.Millennium.exposeObj(exports, ',
|
|
664
|
+
'client.BindPluginSettings()': 'client.BindPluginSettings(pluginName)',
|
|
665
|
+
}),
|
|
666
|
+
babel({ presets: ['@babel/preset-env', '@babel/preset-react'], babelHelpers: 'bundled' }),
|
|
667
|
+
...(Object.keys(env).length > 0 ? [injectProcessEnv(env)] : []),
|
|
668
|
+
];
|
|
669
|
+
const merged = await withUserPlugins(base);
|
|
670
|
+
return this.props.minify ? [...merged, terser()] : merged;
|
|
671
|
+
}
|
|
672
|
+
output(_isMillennium) {
|
|
673
|
+
return {
|
|
674
|
+
name: 'millennium_main',
|
|
675
|
+
file: '.millennium/Dist/webkit.js',
|
|
676
|
+
exports: 'named',
|
|
677
|
+
format: 'iife',
|
|
678
|
+
globals: { '@steambrew/webkit': 'window.MILLENNIUM_API' },
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
const TranspilerPluginComponent = async (isMillennium, pluginJson, props) => {
|
|
683
|
+
const webkitDir = './webkit/index.tsx';
|
|
684
|
+
const frontendDir = getFrontendDir(pluginJson);
|
|
685
|
+
const sysfs = constSysfsExpr();
|
|
821
686
|
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);
|
|
687
|
+
await new FrontendBuild(frontendDir, props).build(resolveEntryFile(frontendDir), sysfs.plugin, isMillennium);
|
|
688
|
+
if (fs.existsSync(webkitDir)) {
|
|
689
|
+
await new WebkitBuild(props).build(webkitDir, sysfs.plugin, isMillennium);
|
|
846
690
|
}
|
|
847
|
-
Logger.
|
|
691
|
+
Logger.done({
|
|
692
|
+
elapsedMs: performance.now() - global.PerfStartTime,
|
|
693
|
+
buildType: props.minify ? 'prod' : 'dev',
|
|
694
|
+
sysfsCount: sysfs.getCount() || undefined,
|
|
695
|
+
envCount: Object.keys(env).length || undefined,
|
|
696
|
+
});
|
|
848
697
|
}
|
|
849
698
|
catch (exception) {
|
|
850
|
-
Logger.
|
|
699
|
+
Logger.error(stripPluginPrefix(exception?.message ?? String(exception)), logLocation(exception));
|
|
851
700
|
process.exit(1);
|
|
852
701
|
}
|
|
853
702
|
};
|
|
@@ -864,18 +713,14 @@ const StartCompilerModule = () => {
|
|
|
864
713
|
const parameters = ValidateParameters(process.argv.slice(2));
|
|
865
714
|
const bIsMillennium = parameters.isMillennium || false;
|
|
866
715
|
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
716
|
ValidatePlugin(bIsMillennium, parameters.targetPlugin)
|
|
869
717
|
.then((json) => {
|
|
870
718
|
const props = {
|
|
871
|
-
|
|
872
|
-
|
|
719
|
+
minify: bTersePlugin,
|
|
720
|
+
pluginName: json?.name,
|
|
873
721
|
};
|
|
874
722
|
TranspilerPluginComponent(bIsMillennium, json, props);
|
|
875
723
|
})
|
|
876
|
-
/**
|
|
877
|
-
* plugin is invalid, we close the proccess as it has already been handled
|
|
878
|
-
*/
|
|
879
724
|
.catch(() => {
|
|
880
725
|
process.exit();
|
|
881
726
|
});
|