@unbound-app/cli 1.1.0 → 1.1.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/dist/index.mjs +452 -413
- package/dist/rollup/index.mjs +31 -112
- package/dist/settings/schema.d.mts +133 -0
- package/dist/settings/schema.mjs +169 -0
- package/dist/{settings-typings-CnJ5F-rP.mjs → settings-typings-BRlzDlLI.mjs} +107 -4
- package/package.json +15 -2
package/dist/rollup/index.mjs
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as reportProblem, C as readLocaleFolder, D as reportLine, E as writeLocaleTypings, F as formatDiagnostic, G as hermesBytecode, K as hermescCount, L as pluginDiagnostic, M as findFile, N as sourceAlias, P as diagnostic, Q as ASSETS_DIRECTORY, R as reportDiagnostic, S as locales, T as sourceLocalePath, U as bytecodeFileName, W as bytecodeSource, a as SETTINGS_MODULE, at as __commonJSMin, b as LOCALE_TYPINGS, c as settingsPath, ct as __require$1, f as outputOnly, g as shim_libraries_default, h as buildReport, i as SETTINGS_FILE, l as lineStarts, lt as __toCommonJS$1, m as DEFAULT_BUDGET, n as settingsTypings, nt as getAssetPath, ot as __esmMin, p as BUILD_REPORT_ENV, r as writeSettingsTypings, rt as isAssetName, s as readPluginSettings, st as __exportAll, u as toLocation, ut as __toESM$1, v as parseByteSize, w as readTable, x as localeModule, y as LOCALE_MODULE, z as reportDiagnostics } from "../settings-typings-BRlzDlLI.mjs";
|
|
2
2
|
import { transformAsync } from "@babel/core";
|
|
3
|
-
import { execFile } from "node:child_process";
|
|
4
|
-
import { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
5
3
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
7
|
-
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
8
7
|
import { Visitor, parseSync, transformSync as transformSync$1 } from "rolldown/utils";
|
|
9
|
-
import { promisify } from "node:util";
|
|
10
|
-
import os, { tmpdir } from "node:os";
|
|
11
8
|
import MagicString from "magic-string";
|
|
12
9
|
import { fileURLToPath } from "node:url";
|
|
13
10
|
import { rollup } from "rollup";
|
|
14
|
-
import { fetchManifest, resolveHermesTargets } from "@unbound-app/rollup-plugin-hermes/manifest";
|
|
15
11
|
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
|
16
12
|
import { minify, swc } from "rollup-plugin-swc3";
|
|
17
13
|
import commonjs from "@rollup/plugin-commonjs";
|
|
@@ -254,104 +250,6 @@ function assets(pluginRoot, collector) {
|
|
|
254
250
|
}
|
|
255
251
|
};
|
|
256
252
|
}
|
|
257
|
-
// src/rollup/hermes-bytecode.ts
|
|
258
|
-
const run = promisify(execFile);
|
|
259
|
-
const FALL_BACK_TO_GLOBAL = /* @__PURE__ */ new Set([
|
|
260
|
-
"unbound",
|
|
261
|
-
"setTimeout",
|
|
262
|
-
"setInterval",
|
|
263
|
-
"clearTimeout",
|
|
264
|
-
"clearInterval"
|
|
265
|
-
]);
|
|
266
|
-
const parameters = ADDON_SCOPE_GLOBALS.map((name) => FALL_BACK_TO_GLOBAL.has(name) ? `${name} = globalThis.${name}` : name).join(", ");
|
|
267
|
-
/**
|
|
268
|
-
* @description Wraps a plugin bundle the way the client evaluates its source, so the compiled program's completion value is the same factory.
|
|
269
|
-
* @param code The plugin's final bundle expression.
|
|
270
|
-
* @returns The wrapped source.
|
|
271
|
-
*/
|
|
272
|
-
function bytecodeSource(code) {
|
|
273
|
-
return `((${parameters}) => { return ${code} })`;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* @description Names the compiled bundle beside a source bundle, matching the loader's lookup.
|
|
277
|
-
* @param fileName The source bundle's file name, such as `index.js`.
|
|
278
|
-
* @param version The Hermes bytecode version.
|
|
279
|
-
* @returns The bytecode file name, such as `index.98.hbc`.
|
|
280
|
-
*/
|
|
281
|
-
function bytecodeFileName(fileName, version) {
|
|
282
|
-
return `${fileName.replace(/\.[^.]+$/, "")}.${version}.hbc`;
|
|
283
|
-
}
|
|
284
|
-
function firstError(error) {
|
|
285
|
-
const output = (error instanceof Error && "stderr" in error && typeof error.stderr === "string" ? error.stderr : void 0) ?? (error instanceof Error ? error.message : String(error));
|
|
286
|
-
return output.split("\n").find((line) => line.includes("error:"))?.trim() ?? output.trim();
|
|
287
|
-
}
|
|
288
|
-
async function compile(hermesc, directory, source, output) {
|
|
289
|
-
await run(hermesc, [
|
|
290
|
-
"--emit-binary",
|
|
291
|
-
"-O",
|
|
292
|
-
"-g1",
|
|
293
|
-
"-Wno-direct-eval",
|
|
294
|
-
"-Wno-undefined-variable",
|
|
295
|
-
"--out",
|
|
296
|
-
output,
|
|
297
|
-
source
|
|
298
|
-
], { cwd: directory });
|
|
299
|
-
return readFile(output);
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* @description Counts how many of hermesc's newest versions to resolve so every wanted version is among them.
|
|
303
|
-
* @param latest hermesc's versions, newest first.
|
|
304
|
-
* @param wanted The bytecode versions to compile for.
|
|
305
|
-
* @returns The number of newest versions to resolve.
|
|
306
|
-
*/
|
|
307
|
-
function hermescCount(latest, wanted) {
|
|
308
|
-
const missing = wanted.filter((version) => !latest.includes(version));
|
|
309
|
-
if (missing.length) throw new Error(`hermesc does not publish bytecode ${missing.join(", ")}.`);
|
|
310
|
-
return Math.max(...wanted.map((version) => latest.indexOf(version)), 0) + 1;
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* @description Compiles each plugin bundle to Hermes bytecode for exactly the bytecode versions the client ships.
|
|
314
|
-
* @param options The bytecode versions to compile for, and the name the bytecode's source locations use.
|
|
315
|
-
* @returns The rollup plugin.
|
|
316
|
-
*/
|
|
317
|
-
function hermesBytecode({ versions, sourceName }) {
|
|
318
|
-
let targets;
|
|
319
|
-
return {
|
|
320
|
-
name: "hermes-bytecode",
|
|
321
|
-
async generateBundle(_outputOptions, bundle) {
|
|
322
|
-
targets ??= (await resolveHermesTargets(this, { versions: hermescCount((await fetchManifest(this)).latest, versions) })).filter((target) => versions.includes(target.version));
|
|
323
|
-
const executable = process.platform === "win32" ? "hermesc.exe" : "hermesc";
|
|
324
|
-
const directory = await mkdtemp(join(tmpdir(), "plugin-bytecode-"));
|
|
325
|
-
try {
|
|
326
|
-
for (const chunk of Object.values(bundle)) {
|
|
327
|
-
if (chunk.type !== "chunk") continue;
|
|
328
|
-
const source = `unbound-plugin/${sourceName}.js`;
|
|
329
|
-
await mkdir(join(directory, "unbound-plugin"), { recursive: true });
|
|
330
|
-
await writeFile(join(directory, source), bytecodeSource(chunk.code));
|
|
331
|
-
for (const { version, dir } of targets) {
|
|
332
|
-
if (!dir) {
|
|
333
|
-
this.warn(`hermesc for bytecode version ${version} is unavailable, skipping it.`);
|
|
334
|
-
continue;
|
|
335
|
-
}
|
|
336
|
-
const compiled = await compile(resolve(dir, process.platform, executable), directory, source, join(directory, `${version}.hbc`)).catch((error) => {
|
|
337
|
-
this.warn(`hermesc ${version} could not compile ${chunk.fileName}, so that runtime loads its source: ${firstError(error)}`);
|
|
338
|
-
});
|
|
339
|
-
if (compiled) this.emitFile({
|
|
340
|
-
type: "asset",
|
|
341
|
-
fileName: bytecodeFileName(chunk.fileName, version),
|
|
342
|
-
source: compiled
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
} finally {
|
|
347
|
-
await rm(directory, {
|
|
348
|
-
recursive: true,
|
|
349
|
-
force: true
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
253
|
// ../client/scripts/build/hermes.json
|
|
356
254
|
var bytecodeVersions = [98];
|
|
357
255
|
// src/rollup/settings-guard.ts
|
|
@@ -43308,9 +43206,9 @@ var import_plugin = /* @__PURE__ */ __toESM$1((/* @__PURE__ */ __commonJSMin(((e
|
|
|
43308
43206
|
var r;
|
|
43309
43207
|
let i = (0, Ar.default)(e).code, n = (0, zr.workletTransformSync)(i, {
|
|
43310
43208
|
extraPlugins: [
|
|
43311
|
-
"@babel/plugin-transform-class-properties",
|
|
43312
|
-
"@babel/plugin-transform-classes",
|
|
43313
|
-
"@babel/plugin-transform-unicode-regex",
|
|
43209
|
+
__require$1.resolve("@babel/plugin-transform-class-properties"),
|
|
43210
|
+
__require$1.resolve("@babel/plugin-transform-classes"),
|
|
43211
|
+
__require$1.resolve("@babel/plugin-transform-unicode-regex"),
|
|
43314
43212
|
...(r = t.opts.extraPlugins) !== null && r !== void 0 ? r : []
|
|
43315
43213
|
],
|
|
43316
43214
|
extraPresets: t.opts.extraPresets,
|
|
@@ -43884,6 +43782,23 @@ function isIdentifierIn(node, names) {
|
|
|
43884
43782
|
}
|
|
43885
43783
|
// src/rollup/worklets.ts
|
|
43886
43784
|
const sourceFile = /\.(m?[jt]sx?)$/;
|
|
43785
|
+
const initData = /^_worklet_\d+_init_data$/;
|
|
43786
|
+
/**
|
|
43787
|
+
* @description Wraps each worklet's code in parentheses, as react-native-worklets' plugin does: its UI runtime evals the code as is, so a bare function declaration evals to undefined, while Reanimated 3 wraps it again harmlessly.
|
|
43788
|
+
* @returns The Babel plugin.
|
|
43789
|
+
*/
|
|
43790
|
+
function parenthesizeWorkletCode() {
|
|
43791
|
+
return {
|
|
43792
|
+
name: "unbound-parenthesize-worklet-code",
|
|
43793
|
+
post(file) {
|
|
43794
|
+
file.path.traverse({ VariableDeclarator(path) {
|
|
43795
|
+
const { id, init } = path.node;
|
|
43796
|
+
if (id.type !== "Identifier" || !initData.test(id.name) || init?.type !== "ObjectExpression") return;
|
|
43797
|
+
for (const property of init.properties) if (property.type === "ObjectProperty" && property.key.type === "Identifier" && property.key.name === "code" && property.value.type === "StringLiteral" && !property.value.value.startsWith("(")) property.value.value = `(${property.value.value})`;
|
|
43798
|
+
} });
|
|
43799
|
+
}
|
|
43800
|
+
};
|
|
43801
|
+
}
|
|
43887
43802
|
/**
|
|
43888
43803
|
* @description Compiles worklets, marked `'worklet'` or passed to an auto-workletizing call such as `useAnimatedStyle`, with the Reanimated version Discord ships, from the source before swc adds helpers the UI runtime cannot call, so plugins can run them on the UI runtime.
|
|
43889
43804
|
* @returns The rollup plugin.
|
|
@@ -43900,10 +43815,14 @@ function worklets() {
|
|
|
43900
43815
|
filename: id,
|
|
43901
43816
|
sourceMaps: true,
|
|
43902
43817
|
presets: typescript ? [typescriptPreset] : [],
|
|
43903
|
-
plugins: [
|
|
43904
|
-
|
|
43905
|
-
|
|
43906
|
-
|
|
43818
|
+
plugins: [
|
|
43819
|
+
jsxSyntax,
|
|
43820
|
+
[import_plugin.default, {
|
|
43821
|
+
relativeSourceLocation: true,
|
|
43822
|
+
disableSourceMaps: true
|
|
43823
|
+
}],
|
|
43824
|
+
parenthesizeWorkletCode
|
|
43825
|
+
]
|
|
43907
43826
|
});
|
|
43908
43827
|
if (!result?.code) return null;
|
|
43909
43828
|
return {
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { TSchema } from "typebox";
|
|
2
|
+
/** A value one schema-declared setting holds. */
|
|
3
|
+
type SettingPrimitive = string | number | boolean;
|
|
4
|
+
/** A value any schema-declared setting holds. */
|
|
5
|
+
type SettingValue = SettingPrimitive | string[];
|
|
6
|
+
type OptionLabel = string | {
|
|
7
|
+
title: string;
|
|
8
|
+
subtitle?: string;
|
|
9
|
+
};
|
|
10
|
+
/** A settings.ts predicate: it reads every setting and says whether a row shows or is enabled. */
|
|
11
|
+
type Predicate = (settings: never) => boolean;
|
|
12
|
+
/** Every builder's options; the generated typings narrow them per builder and `displayAs`. */
|
|
13
|
+
export type BuilderOptions = {
|
|
14
|
+
title?: string;
|
|
15
|
+
subtitle?: string;
|
|
16
|
+
hidden?: boolean;
|
|
17
|
+
requiresRestart?: boolean;
|
|
18
|
+
visibleWhen?: string | Predicate;
|
|
19
|
+
disabledWhen?: string | Predicate;
|
|
20
|
+
displayAs?: string;
|
|
21
|
+
default?: SettingValue;
|
|
22
|
+
min?: number;
|
|
23
|
+
max?: number;
|
|
24
|
+
step?: number;
|
|
25
|
+
units?: string[];
|
|
26
|
+
minLength?: number;
|
|
27
|
+
maxLength?: number;
|
|
28
|
+
placeholder?: string;
|
|
29
|
+
alpha?: boolean;
|
|
30
|
+
presets?: string[];
|
|
31
|
+
palette?: boolean;
|
|
32
|
+
maxSize?: number;
|
|
33
|
+
options?: Record<string, OptionLabel>;
|
|
34
|
+
of?: TSchema;
|
|
35
|
+
minItems?: number;
|
|
36
|
+
maxItems?: number;
|
|
37
|
+
action?: string;
|
|
38
|
+
confirm?: string;
|
|
39
|
+
tone?: string;
|
|
40
|
+
};
|
|
41
|
+
/** The options of `defineSettings`. */
|
|
42
|
+
export type DefineOptions = {
|
|
43
|
+
title?: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* @description Builds a `boolean` setting.
|
|
47
|
+
* @param options Its labels, default and display.
|
|
48
|
+
* @returns Its schema.
|
|
49
|
+
*/
|
|
50
|
+
declare function boolean(options: BuilderOptions): TSchema;
|
|
51
|
+
/**
|
|
52
|
+
* @description Builds a `number` setting.
|
|
53
|
+
* @param options Its labels, default, range and display.
|
|
54
|
+
* @returns Its schema.
|
|
55
|
+
*/
|
|
56
|
+
declare function number(options: BuilderOptions): TSchema;
|
|
57
|
+
/**
|
|
58
|
+
* @description Builds a whole-number setting.
|
|
59
|
+
* @param options Its labels, default, range and display.
|
|
60
|
+
* @returns Its schema.
|
|
61
|
+
*/
|
|
62
|
+
declare function integer(options: BuilderOptions): TSchema;
|
|
63
|
+
/**
|
|
64
|
+
* @description Builds a `string` setting, or with no options an `array` item.
|
|
65
|
+
* @param options Its labels, default, display and the display's options.
|
|
66
|
+
* @returns Its schema.
|
|
67
|
+
*/
|
|
68
|
+
declare function string(options?: BuilderOptions): TSchema;
|
|
69
|
+
/**
|
|
70
|
+
* @description Builds a setting holding one of its options' keys, or with only `options` an `array` item.
|
|
71
|
+
* @param options Its labels, default, options and display.
|
|
72
|
+
* @returns Its schema.
|
|
73
|
+
*/
|
|
74
|
+
declare function choice(options: BuilderOptions): TSchema;
|
|
75
|
+
/**
|
|
76
|
+
* @description Builds a list setting of `of` items.
|
|
77
|
+
* @param options Its labels, item, limits and display.
|
|
78
|
+
* @returns Its schema.
|
|
79
|
+
*/
|
|
80
|
+
declare function array(options: BuilderOptions): TSchema;
|
|
81
|
+
/**
|
|
82
|
+
* @description Builds a section of settings.
|
|
83
|
+
* @param options Its labels and display.
|
|
84
|
+
* @param properties Its settings and buttons.
|
|
85
|
+
* @returns Its schema.
|
|
86
|
+
*/
|
|
87
|
+
declare function section(options: BuilderOptions, properties: Record<string, TSchema>): TSchema;
|
|
88
|
+
/**
|
|
89
|
+
* @description Builds a button row that runs an export of src/actions.ts; it stores nothing.
|
|
90
|
+
* @param options Its labels, action, confirmation and display.
|
|
91
|
+
* @returns Its schema.
|
|
92
|
+
*/
|
|
93
|
+
declare function button(options: BuilderOptions): TSchema;
|
|
94
|
+
/**
|
|
95
|
+
* @description Builds a notice row that shows a message in its panel; it stores nothing.
|
|
96
|
+
* @param options Its labels, tone and `visibleWhen`.
|
|
97
|
+
* @returns Its schema.
|
|
98
|
+
*/
|
|
99
|
+
declare function notice(options: BuilderOptions): TSchema;
|
|
100
|
+
/** The setting builders, one per stored primitive; `displayAs` picks the widget. */
|
|
101
|
+
export declare const setting: {
|
|
102
|
+
boolean: typeof boolean;
|
|
103
|
+
number: typeof number;
|
|
104
|
+
integer: typeof integer;
|
|
105
|
+
string: typeof string;
|
|
106
|
+
choice: typeof choice;
|
|
107
|
+
array: typeof array;
|
|
108
|
+
section: typeof section;
|
|
109
|
+
button: typeof button;
|
|
110
|
+
notice: typeof notice;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* @description Declares a plugin's settings: the default export of its settings.ts.
|
|
114
|
+
* @param properties The settings, sections and buttons, built with {@link setting}.
|
|
115
|
+
* @param options The message key of the title of the section holding the top-level settings.
|
|
116
|
+
* @returns The TypeBox object schema, marked as a settings schema.
|
|
117
|
+
*/
|
|
118
|
+
export declare function defineSettings(properties: Record<string, TSchema>, options?: DefineOptions): TSchema;
|
|
119
|
+
declare const _default: {
|
|
120
|
+
defineSettings: typeof defineSettings;
|
|
121
|
+
setting: {
|
|
122
|
+
boolean: typeof boolean;
|
|
123
|
+
number: typeof number;
|
|
124
|
+
integer: typeof integer;
|
|
125
|
+
string: typeof string;
|
|
126
|
+
choice: typeof choice;
|
|
127
|
+
array: typeof array;
|
|
128
|
+
section: typeof section;
|
|
129
|
+
button: typeof button;
|
|
130
|
+
notice: typeof notice;
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
export { _default as default };
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import Type$1 from "typebox";
|
|
2
|
+
// src/settings/schema.ts
|
|
3
|
+
function defined(values) {
|
|
4
|
+
return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== void 0));
|
|
5
|
+
}
|
|
6
|
+
function condition(value) {
|
|
7
|
+
return typeof value === "function" ? { predicate: true } : value;
|
|
8
|
+
}
|
|
9
|
+
function meta(kind, displayAs, options, extra = {}) {
|
|
10
|
+
return {
|
|
11
|
+
kind,
|
|
12
|
+
displayAs,
|
|
13
|
+
...defined({
|
|
14
|
+
title: options.title,
|
|
15
|
+
subtitle: options.subtitle,
|
|
16
|
+
hidden: options.hidden,
|
|
17
|
+
requiresRestart: options.requiresRestart,
|
|
18
|
+
visibleWhen: condition(options.visibleWhen),
|
|
19
|
+
disabledWhen: condition(options.disabledWhen),
|
|
20
|
+
default: options.default,
|
|
21
|
+
...extra
|
|
22
|
+
})
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function numeric(kind, options) {
|
|
26
|
+
const ranged = options.min !== void 0 && options.max !== void 0;
|
|
27
|
+
return meta(kind, options.displayAs ?? (ranged ? "slider" : "input"), options, {
|
|
28
|
+
minimum: options.min,
|
|
29
|
+
maximum: options.max,
|
|
30
|
+
multipleOf: options.step,
|
|
31
|
+
units: options.units
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function choices({ options = {} }) {
|
|
35
|
+
return Object.entries(options).map(([value, label]) => typeof label === "string" ? {
|
|
36
|
+
const: value,
|
|
37
|
+
title: label
|
|
38
|
+
} : {
|
|
39
|
+
const: value,
|
|
40
|
+
...label
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* @description Builds a `boolean` setting.
|
|
45
|
+
* @param options Its labels, default and display.
|
|
46
|
+
* @returns Its schema.
|
|
47
|
+
*/
|
|
48
|
+
function boolean(options) {
|
|
49
|
+
return Type$1.Boolean(meta("boolean", options.displayAs ?? "switch", options));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* @description Builds a `number` setting.
|
|
53
|
+
* @param options Its labels, default, range and display.
|
|
54
|
+
* @returns Its schema.
|
|
55
|
+
*/
|
|
56
|
+
function number(options) {
|
|
57
|
+
return Type$1.Number(numeric("number", options));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* @description Builds a whole-number setting.
|
|
61
|
+
* @param options Its labels, default, range and display.
|
|
62
|
+
* @returns Its schema.
|
|
63
|
+
*/
|
|
64
|
+
function integer(options) {
|
|
65
|
+
return Type$1.Integer(numeric("integer", options));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* @description Builds a `string` setting, or with no options an `array` item.
|
|
69
|
+
* @param options Its labels, default, display and the display's options.
|
|
70
|
+
* @returns Its schema.
|
|
71
|
+
*/
|
|
72
|
+
function string(options = {}) {
|
|
73
|
+
return Type$1.String(meta("string", options.displayAs ?? "input", {
|
|
74
|
+
default: "",
|
|
75
|
+
...options
|
|
76
|
+
}, {
|
|
77
|
+
minLength: options.minLength,
|
|
78
|
+
maxLength: options.maxLength,
|
|
79
|
+
placeholder: options.placeholder,
|
|
80
|
+
alpha: options.alpha,
|
|
81
|
+
presets: options.presets,
|
|
82
|
+
palette: options.palette,
|
|
83
|
+
maxSize: options.maxSize
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* @description Builds a setting holding one of its options' keys, or with only `options` an `array` item.
|
|
88
|
+
* @param options Its labels, default, options and display.
|
|
89
|
+
* @returns Its schema.
|
|
90
|
+
*/
|
|
91
|
+
function choice(options) {
|
|
92
|
+
const list = choices(options);
|
|
93
|
+
const displayAs = options.displayAs ?? (list.length > 5 ? "picker" : "radio");
|
|
94
|
+
return Type$1.Union(list.map((option) => Type$1.Literal(option.const)), meta("choice", displayAs, options, { options: list }));
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* @description Builds a list setting of `of` items.
|
|
98
|
+
* @param options Its labels, item, limits and display.
|
|
99
|
+
* @returns Its schema.
|
|
100
|
+
*/
|
|
101
|
+
function array(options) {
|
|
102
|
+
const item = Object.fromEntries(Object.entries(options.of ?? {}).filter(([key]) => key !== "default"));
|
|
103
|
+
const displayAs = options.displayAs ?? (item.kind === "choice" ? "checkboxes" : "list");
|
|
104
|
+
return Type$1.Array(Type$1.Unknown(), meta("array", displayAs, {
|
|
105
|
+
default: [],
|
|
106
|
+
...options
|
|
107
|
+
}, {
|
|
108
|
+
minItems: options.minItems,
|
|
109
|
+
maxItems: options.maxItems,
|
|
110
|
+
of: item
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* @description Builds a section of settings.
|
|
115
|
+
* @param options Its labels and display.
|
|
116
|
+
* @param properties Its settings and buttons.
|
|
117
|
+
* @returns Its schema.
|
|
118
|
+
*/
|
|
119
|
+
function section(options, properties) {
|
|
120
|
+
return Type$1.Object(properties, meta("section", options.displayAs ?? "group", options));
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* @description Builds a button row that runs an export of src/actions.ts; it stores nothing.
|
|
124
|
+
* @param options Its labels, action, confirmation and display.
|
|
125
|
+
* @returns Its schema.
|
|
126
|
+
*/
|
|
127
|
+
function button(options) {
|
|
128
|
+
return Type$1.Null(meta("button", options.displayAs ?? "button", options, {
|
|
129
|
+
action: options.action,
|
|
130
|
+
confirm: options.confirm
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* @description Builds a notice row that shows a message in its panel; it stores nothing.
|
|
135
|
+
* @param options Its labels, tone and `visibleWhen`.
|
|
136
|
+
* @returns Its schema.
|
|
137
|
+
*/
|
|
138
|
+
function notice(options) {
|
|
139
|
+
return Type$1.Null(meta("notice", "notice", options, { tone: options.tone ?? "info" }));
|
|
140
|
+
}
|
|
141
|
+
/** The setting builders, one per stored primitive; `displayAs` picks the widget. */
|
|
142
|
+
const setting = {
|
|
143
|
+
boolean,
|
|
144
|
+
number,
|
|
145
|
+
integer,
|
|
146
|
+
string,
|
|
147
|
+
choice,
|
|
148
|
+
array,
|
|
149
|
+
section,
|
|
150
|
+
button,
|
|
151
|
+
notice
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* @description Declares a plugin's settings: the default export of its settings.ts.
|
|
155
|
+
* @param properties The settings, sections and buttons, built with {@link setting}.
|
|
156
|
+
* @param options The message key of the title of the section holding the top-level settings.
|
|
157
|
+
* @returns The TypeBox object schema, marked as a settings schema.
|
|
158
|
+
*/
|
|
159
|
+
function defineSettings(properties, options = {}) {
|
|
160
|
+
return Type$1.Object(properties, defined({
|
|
161
|
+
kind: "settings",
|
|
162
|
+
title: options.title
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
var schema_default = {
|
|
166
|
+
defineSettings,
|
|
167
|
+
setting
|
|
168
|
+
};
|
|
169
|
+
export { schema_default as default, defineSettings, setting };
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { Type } from "typebox";
|
|
3
3
|
import { Value } from "typebox/value";
|
|
4
|
-
import {
|
|
4
|
+
import { execFile } from "node:child_process";
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
8
|
+
import { fetchManifest, resolveHermesTargets } from "@unbound-app/rollup-plugin-hermes/manifest";
|
|
9
|
+
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
10
|
+
import { promisify } from "node:util";
|
|
6
11
|
import { createHash } from "node:crypto";
|
|
7
|
-
import { writeFile } from "node:fs/promises";
|
|
8
12
|
import { parseSync } from "rolldown/utils";
|
|
9
13
|
import { gzipSync } from "node:zlib";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
10
15
|
import { rolldown } from "rolldown";
|
|
11
16
|
// \0rolldown/runtime.js
|
|
12
17
|
var __create = Object.create;
|
|
@@ -173,6 +178,104 @@ function listAddonFiles(manifest) {
|
|
|
173
178
|
}
|
|
174
179
|
return [...files.values()];
|
|
175
180
|
}
|
|
181
|
+
// src/rollup/hermes-bytecode.ts
|
|
182
|
+
const run = promisify(execFile);
|
|
183
|
+
const FALL_BACK_TO_GLOBAL = /* @__PURE__ */ new Set([
|
|
184
|
+
"unbound",
|
|
185
|
+
"setTimeout",
|
|
186
|
+
"setInterval",
|
|
187
|
+
"clearTimeout",
|
|
188
|
+
"clearInterval"
|
|
189
|
+
]);
|
|
190
|
+
const parameters = ADDON_SCOPE_GLOBALS.map((name) => FALL_BACK_TO_GLOBAL.has(name) ? `${name} = globalThis.${name}` : name).join(", ");
|
|
191
|
+
/**
|
|
192
|
+
* @description Wraps a plugin bundle the way the client evaluates its source, so the compiled program's completion value is the same factory.
|
|
193
|
+
* @param code The plugin's final bundle expression.
|
|
194
|
+
* @returns The wrapped source.
|
|
195
|
+
*/
|
|
196
|
+
function bytecodeSource(code) {
|
|
197
|
+
return `((${parameters}) => { return ${code} })`;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* @description Names the compiled bundle beside a source bundle, matching the loader's lookup.
|
|
201
|
+
* @param fileName The source bundle's file name, such as `index.js`.
|
|
202
|
+
* @param version The Hermes bytecode version.
|
|
203
|
+
* @returns The bytecode file name, such as `index.98.hbc`.
|
|
204
|
+
*/
|
|
205
|
+
function bytecodeFileName(fileName, version) {
|
|
206
|
+
return `${fileName.replace(/\.[^.]+$/, "")}.${version}.hbc`;
|
|
207
|
+
}
|
|
208
|
+
function firstError(error) {
|
|
209
|
+
const output = (error instanceof Error && "stderr" in error && typeof error.stderr === "string" ? error.stderr : void 0) ?? (error instanceof Error ? error.message : String(error));
|
|
210
|
+
return output.split("\n").find((line) => line.includes("error:"))?.trim() ?? output.trim();
|
|
211
|
+
}
|
|
212
|
+
async function compile(hermesc, directory, source, output) {
|
|
213
|
+
await run(hermesc, [
|
|
214
|
+
"--emit-binary",
|
|
215
|
+
"-O",
|
|
216
|
+
"-g1",
|
|
217
|
+
"-Wno-direct-eval",
|
|
218
|
+
"-Wno-undefined-variable",
|
|
219
|
+
"--out",
|
|
220
|
+
output,
|
|
221
|
+
source
|
|
222
|
+
], { cwd: directory });
|
|
223
|
+
return readFile(output);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* @description Counts how many of hermesc's newest versions to resolve so every wanted version is among them.
|
|
227
|
+
* @param latest hermesc's versions, newest first.
|
|
228
|
+
* @param wanted The bytecode versions to compile for.
|
|
229
|
+
* @returns The number of newest versions to resolve.
|
|
230
|
+
*/
|
|
231
|
+
function hermescCount(latest, wanted) {
|
|
232
|
+
const missing = wanted.filter((version) => !latest.includes(version));
|
|
233
|
+
if (missing.length) throw new Error(`hermesc does not publish bytecode ${missing.join(", ")}.`);
|
|
234
|
+
return Math.max(...wanted.map((version) => latest.indexOf(version)), 0) + 1;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* @description Compiles each plugin bundle to Hermes bytecode for exactly the bytecode versions the client ships.
|
|
238
|
+
* @param options The bytecode versions to compile for, and the name the bytecode's source locations use.
|
|
239
|
+
* @returns The rollup plugin.
|
|
240
|
+
*/
|
|
241
|
+
function hermesBytecode({ versions, sourceName }) {
|
|
242
|
+
let targets;
|
|
243
|
+
return {
|
|
244
|
+
name: "hermes-bytecode",
|
|
245
|
+
async generateBundle(_outputOptions, bundle) {
|
|
246
|
+
targets ??= (await resolveHermesTargets(this, { versions: hermescCount((await fetchManifest(this)).latest, versions) })).filter((target) => versions.includes(target.version));
|
|
247
|
+
const executable = process.platform === "win32" ? "hermesc.exe" : "hermesc";
|
|
248
|
+
const directory = await mkdtemp(join(tmpdir(), "plugin-bytecode-"));
|
|
249
|
+
try {
|
|
250
|
+
for (const chunk of Object.values(bundle)) {
|
|
251
|
+
if (chunk.type !== "chunk") continue;
|
|
252
|
+
const source = `unbound-plugin/${sourceName}.js`;
|
|
253
|
+
await mkdir(join(directory, "unbound-plugin"), { recursive: true });
|
|
254
|
+
await writeFile(join(directory, source), bytecodeSource(chunk.code));
|
|
255
|
+
for (const { version, dir } of targets) {
|
|
256
|
+
if (!dir) {
|
|
257
|
+
this.warn(`hermesc for bytecode version ${version} is unavailable, skipping it.`);
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const compiled = await compile(resolve(dir, process.platform, executable), directory, source, join(directory, `${version}.hbc`)).catch((error) => {
|
|
261
|
+
this.warn(`hermesc ${version} could not compile ${chunk.fileName}, so that runtime loads its source: ${firstError(error)}`);
|
|
262
|
+
});
|
|
263
|
+
if (compiled) this.emitFile({
|
|
264
|
+
type: "asset",
|
|
265
|
+
fileName: bytecodeFileName(chunk.fileName, version),
|
|
266
|
+
source: compiled
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
} finally {
|
|
271
|
+
await rm(directory, {
|
|
272
|
+
recursive: true,
|
|
273
|
+
force: true
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
176
279
|
// src/rollup/diagnostic.ts
|
|
177
280
|
const SEVERITIES = ["error", "warning"];
|
|
178
281
|
/**
|
|
@@ -2033,7 +2136,7 @@ const SETTINGS_FILE = "settings.ts";
|
|
|
2033
2136
|
const SETTINGS_MODULE = "@unbound-app/settings";
|
|
2034
2137
|
/** The build-time module `settings.ts` imports its builders from; it exists only while the build evaluates the file. */
|
|
2035
2138
|
const SETTINGS_SCHEMA_MODULE = "@unbound-app/settings/schema";
|
|
2036
|
-
const BUILDERS =
|
|
2139
|
+
const BUILDERS = fileURLToPath(import.meta.resolve("@unbound-app/cli/settings/schema"));
|
|
2037
2140
|
/**
|
|
2038
2141
|
* @description Names a plugin's settings schema file.
|
|
2039
2142
|
* @param pluginRoot The plugin's directory.
|
|
@@ -2479,4 +2582,4 @@ function writeSettingsTypings(pluginRoot, typings) {
|
|
|
2479
2582
|
writeFileSync(path, typings);
|
|
2480
2583
|
return true;
|
|
2481
2584
|
}
|
|
2482
|
-
export {
|
|
2585
|
+
export { ASSET_NAME_PATTERN as $, readIcuMessage as A, reportProblem as B, readLocaleFolder as C, reportLine as D, writeLocaleTypings as E, formatDiagnostic as F, hermesBytecode as G, withoutFullStop as H, isDiagnostic as I, LOCALES_DIRECTORY as J, hermescCount as K, pluginDiagnostic as L, findFile as M, sourceAlias as N, buildReportSchema as O, diagnostic as P, ASSETS_DIRECTORY as Q, reportDiagnostic as R, locales as S, sourceLocalePath as T, bytecodeFileName as U, sortDiagnostics as V, bytecodeSource as W, SOURCE_LOCALE as X, LOCALE_CODE_PATTERN as Y, isLocaleCode as Z, formatBytes as _, SETTINGS_MODULE as a, __commonJSMin as at, LOCALE_TYPINGS as b, settingsPath as c, __require as ct, OUTPUT_ONLY as d, ASSET_SCALES as et, outputOnly as f, shim_libraries_default as g, buildReport as h, SETTINGS_FILE as i, ADDON_KINDS as it, IcuSyntaxError as j, readIcuArguments as k, lineStarts as l, __toCommonJS as lt, DEFAULT_BUDGET as m, settingsTypings as n, getAssetPath as nt, SETTINGS_SCHEMA_MODULE as o, __esmMin as ot, BUILD_REPORT_ENV as p, listAddonFiles as q, writeSettingsTypings as r, isAssetName as rt, readPluginSettings as s, __exportAll as st, SETTINGS_TYPINGS as t, ASSET_TYPES as tt, toLocation as u, __toESM as ut, parseByteSize as v, readTable as w, localeModule as x, LOCALE_MODULE as y, reportDiagnostics as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unbound-app/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "The `ubd` command line for the Unbound client: evaluate on-device code and serve the debugger as an MCP.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mario P.",
|
|
@@ -33,6 +33,10 @@
|
|
|
33
33
|
"./oxlint": {
|
|
34
34
|
"types": "./dist/oxlint/plugin.d.mts",
|
|
35
35
|
"import": "./dist/oxlint/plugin.mjs"
|
|
36
|
+
},
|
|
37
|
+
"./settings/schema": {
|
|
38
|
+
"types": "./dist/settings/schema.d.mts",
|
|
39
|
+
"import": "./dist/settings/schema.mjs"
|
|
36
40
|
}
|
|
37
41
|
},
|
|
38
42
|
"scripts": {
|
|
@@ -42,14 +46,23 @@
|
|
|
42
46
|
"dependencies": {
|
|
43
47
|
"@babel/core": "^7.29.7",
|
|
44
48
|
"@babel/plugin-syntax-jsx": "^8.0.1",
|
|
49
|
+
"@babel/plugin-transform-arrow-functions": "^7.29.7",
|
|
45
50
|
"@babel/plugin-transform-block-scoping": "^8.0.10",
|
|
51
|
+
"@babel/plugin-transform-class-properties": "^7.29.7",
|
|
52
|
+
"@babel/plugin-transform-classes": "^7.29.7",
|
|
53
|
+
"@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7",
|
|
54
|
+
"@babel/plugin-transform-optional-chaining": "^7.29.7",
|
|
55
|
+
"@babel/plugin-transform-shorthand-properties": "^7.29.7",
|
|
56
|
+
"@babel/plugin-transform-template-literals": "^7.29.7",
|
|
57
|
+
"@babel/plugin-transform-unicode-regex": "^7.29.7",
|
|
46
58
|
"@babel/preset-typescript": "^8.0.7",
|
|
47
59
|
"@clack/prompts": "^1.8.1",
|
|
48
60
|
"@modelcontextprotocol/sdk": "^1.32.2",
|
|
49
61
|
"@rollup/plugin-commonjs": "^29.0.3",
|
|
50
62
|
"@rollup/plugin-json": "^6.1.0",
|
|
51
63
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
52
|
-
"@unbound-app/debugger
|
|
64
|
+
"@unbound-app/debugger": "0.10.2",
|
|
65
|
+
"@unbound-app/debugger-protocol": "0.11.1",
|
|
53
66
|
"@unbound-app/rollup-plugin-hermes": "2.0.0",
|
|
54
67
|
"better-auth": "1.7.16",
|
|
55
68
|
"cleye": "^2.7.0",
|