muon-ui 0.26.0 → 0.26.47
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/README.md +5 -0
- package/android.d.ts +4 -4
- package/dist/android/lib/index.cjs +13 -10
- package/dist/android/lib/index.cjs.map +1 -1
- package/dist/android/lib/index.mjs +14 -11
- package/dist/android/lib/index.mjs.map +1 -1
- package/dist/android/maven/dev/muon/runtime/0.1.0/runtime-0.1.0.aar +0 -0
- package/dist/android/maven/dev/muon/runtime/0.1.0/runtime-0.1.0.aar.md5 +1 -1
- package/dist/android/maven/dev/muon/runtime/0.1.0/runtime-0.1.0.aar.sha1 +1 -1
- package/dist/android/maven/dev/muon/runtime/0.1.0/runtime-0.1.0.aar.sha256 +1 -1
- package/dist/android/maven/dev/muon/runtime/0.1.0/runtime-0.1.0.aar.sha512 +1 -1
- package/dist/android/maven/dev/muon/runtime/0.1.0/runtime-0.1.0.module +10 -10
- package/dist/android/maven/dev/muon/runtime/0.1.0/runtime-0.1.0.module.md5 +1 -1
- package/dist/android/maven/dev/muon/runtime/0.1.0/runtime-0.1.0.module.sha1 +1 -1
- package/dist/android/maven/dev/muon/runtime/0.1.0/runtime-0.1.0.module.sha256 +1 -1
- package/dist/android/maven/dev/muon/runtime/0.1.0/runtime-0.1.0.module.sha512 +1 -1
- package/dist/android/maven/dev/muon/runtime/maven-metadata.xml +1 -1
- package/dist/android/maven/dev/muon/runtime/maven-metadata.xml.md5 +1 -1
- package/dist/android/maven/dev/muon/runtime/maven-metadata.xml.sha1 +1 -1
- package/dist/android/maven/dev/muon/runtime/maven-metadata.xml.sha256 +1 -1
- package/dist/android/maven/dev/muon/runtime/maven-metadata.xml.sha512 +1 -1
- package/dist/android/renderer/renderer.js +41 -14
- package/dist/android/renderer/renderer.js.map +1 -1
- package/dist/cli.cjs +82 -56
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/native/linux-amd64/muon-builder +0 -0
- package/dist/native/linux-amd64/muon-launcher +0 -0
- package/dist/native/linux-amd64/muon-runtime-helper +0 -0
- package/dist/native/linux-arm64/muon-builder +0 -0
- package/dist/native/linux-arm64/muon-launcher +0 -0
- package/dist/native/linux-arm64/muon-runtime-helper +0 -0
- package/dist/native/linux-armhf/muon-builder +0 -0
- package/dist/native/linux-armhf/muon-launcher +0 -0
- package/dist/native/linux-armhf/muon-runtime-helper +0 -0
- package/dist/native/windows-amd64/muon-builder.exe +0 -0
- package/dist/native/windows-amd64/muon-launcher.exe +0 -0
- package/dist/native/windows-amd64/muon-plugin-inspector.exe +0 -0
- package/dist/native/windows-i686/muon-builder.exe +0 -0
- package/dist/native/windows-i686/muon-launcher.exe +0 -0
- package/dist/native/windows-i686/muon-plugin-inspector.exe +0 -0
- package/dist/runtime/linux-amd64/libmuon-ui.so +0 -0
- package/dist/runtime/linux-amd64/muon-core +0 -0
- package/dist/runtime/linux-amd64/plugins/node-bridge.mjs +5 -5
- package/dist/runtime/linux-amd64/plugins/node.so +0 -0
- package/dist/runtime/linux-arm64/libmuon-ui.so +0 -0
- package/dist/runtime/linux-arm64/muon-core +0 -0
- package/dist/runtime/linux-arm64/plugins/node-bridge.mjs +5 -5
- package/dist/runtime/linux-arm64/plugins/node.so +0 -0
- package/dist/runtime/linux-armhf/libmuon-ui.so +0 -0
- package/dist/runtime/linux-armhf/muon-core +0 -0
- package/dist/runtime/linux-armhf/plugins/node-bridge.mjs +5 -5
- package/dist/runtime/linux-armhf/plugins/node.so +0 -0
- package/dist/runtime/windows-amd64/libcardio.dll +0 -0
- package/dist/runtime/windows-amd64/libmuon-ui.dll +0 -0
- package/dist/runtime/windows-amd64/muon-core.exe +0 -0
- package/dist/runtime/windows-amd64/plugins/node-bridge.mjs +5 -5
- package/dist/runtime/windows-amd64/plugins/node.dll +0 -0
- package/dist/runtime/windows-i686/libcardio.dll +0 -0
- package/dist/runtime/windows-i686/libmuon-ui.dll +0 -0
- package/dist/runtime/windows-i686/muon-core.exe +0 -0
- package/dist/runtime/windows-i686/plugins/node-bridge.mjs +5 -5
- package/dist/runtime/windows-i686/plugins/node.dll +0 -0
- package/dist/{vite-internals-DseKep-X.cjs → vite-internals-CueaxMaY.cjs} +4225 -1963
- package/dist/vite-internals-CueaxMaY.cjs.map +1 -0
- package/dist/vite.cjs +100 -1294
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +6102 -5128
- package/dist/vite.mjs.map +1 -1
- package/images/get-started-android.png +0 -0
- package/muon-virtual-modules.d.ts +53 -0
- package/package.json +13 -13
- package/vite.d.ts +8 -0
- package/dist/vite-internals-DseKep-X.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -53,6 +53,10 @@ This lets you build modern local GUI applications with the web technology ecosys
|
|
|
53
53
|
muon also minimizes the steps required to create a muon application, keeping the barrier to entry low.
|
|
54
54
|
With the minimal setup, installing the NPM package and adding one line to the configuration file is enough to launch your first muon app.
|
|
55
55
|
|
|
56
|
+
WIP: And once you've created a muon application, you can deploy it directly to Android.
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
56
60
|
### Features
|
|
57
61
|
|
|
58
62
|
- Restricts all network access through a whitelist filter, letting you completely exclude problematic content.
|
|
@@ -63,6 +67,7 @@ With the minimal setup, installing the NPM package and adding one line to the co
|
|
|
63
67
|
- You can also build Android applications (experimental).
|
|
64
68
|
- DevTools can be used. CDP (Chrome DevTools Protocol) is also supported, so remote debugging from external tools is possible.
|
|
65
69
|
- Includes a plugin system. Plugin capabilities can also be restricted by a whitelist filter.
|
|
70
|
+
- An independent SDK supports C/C++ plugin development and distribution as prebuilt NPM packages.
|
|
66
71
|
- Built-in plugins provide access to local files, open dialogs, child process launching, and window operations.
|
|
67
72
|
|
|
68
73
|
### Environment
|
package/android.d.ts
CHANGED
|
@@ -14,10 +14,10 @@ export interface MuonAndroidPluginOptions {
|
|
|
14
14
|
soname: string;
|
|
15
15
|
/** Library path for each ABI selected by android.abis. */
|
|
16
16
|
libraries: Partial<Record<MuonAndroidAbi, string>>;
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
|
|
17
|
+
/** Ordinary shared dependencies by ABI, copied beside the plugin. */
|
|
18
|
+
dependencies?: Partial<Record<MuonAndroidAbi, readonly string[]>>;
|
|
19
|
+
/** Producer catalog JSON path, required for validate mode; resolved like libraries. */
|
|
20
|
+
metadata?: string;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/** Android application options, overriding the muon.json android section. */
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* name: muon-
|
|
3
|
-
* version: 0.26.
|
|
4
|
-
* description:
|
|
2
|
+
* name: muon-ui
|
|
3
|
+
* version: 0.26.47
|
|
4
|
+
* description: A multi-platform GUI application framework that uses CEF as its backend
|
|
5
5
|
* author: Kouji Matsui (@kekyo@mi.kekyo.net)
|
|
6
6
|
* license: MIT
|
|
7
7
|
* repository.url: https://github.com/kekyo/muon-ui.git
|
|
8
|
-
* git.commit.hash:
|
|
8
|
+
* git.commit.hash: 95dc2712686873c8a022483fd9abf18598019bd7
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
11
11
|
let node_fs_promises = require("node:fs/promises");
|
|
@@ -15,7 +15,7 @@ let funcity = require("funcity");
|
|
|
15
15
|
let node_child_process = require("node:child_process");
|
|
16
16
|
let node_fs = require("node:fs");
|
|
17
17
|
let node_os = require("node:os");
|
|
18
|
-
//#region
|
|
18
|
+
//#region android/command.ts
|
|
19
19
|
/**
|
|
20
20
|
* Runs a build tool without a shell and awaits process completion.
|
|
21
21
|
* @param command - Executable path.
|
|
@@ -50,7 +50,7 @@ var runAndroidCommand = async (command, args, cwd, environment, output) => await
|
|
|
50
50
|
});
|
|
51
51
|
});
|
|
52
52
|
//#endregion
|
|
53
|
-
//#region
|
|
53
|
+
//#region android/toolchain.ts
|
|
54
54
|
var accessible = async (path, mode) => {
|
|
55
55
|
try {
|
|
56
56
|
await (0, node_fs_promises.access)(path, mode);
|
|
@@ -109,7 +109,7 @@ var prepareAndroid = async (options) => {
|
|
|
109
109
|
};
|
|
110
110
|
};
|
|
111
111
|
//#endregion
|
|
112
|
-
//#region
|
|
112
|
+
//#region android/build.ts
|
|
113
113
|
var xml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
114
114
|
var render = async (template, variables) => {
|
|
115
115
|
const logs = [];
|
|
@@ -162,15 +162,17 @@ var buildAndroidApplication = async (input) => {
|
|
|
162
162
|
await (0, node_fs_promises.copyFile)((0, node_path.join)(tools.componentsDirectory, "renderer/renderer.js"), (0, node_path.join)(frameworkAssets, "renderer.js"));
|
|
163
163
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(frameworkAssets, "config.json"), JSON.stringify({
|
|
164
164
|
startPage: input.startPage,
|
|
165
|
-
values: input.values
|
|
165
|
+
values: input.values,
|
|
166
|
+
plugin: input.pluginAccess
|
|
166
167
|
}));
|
|
167
168
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(frameworkAssets, "plugins.json"), JSON.stringify({
|
|
168
169
|
schemaVersion: 1,
|
|
169
|
-
plugins: input.plugins.map(({ name, soname, allow, config }) => ({
|
|
170
|
+
plugins: input.plugins.map(({ name, soname, allow, config, expectedFunctions }) => ({
|
|
170
171
|
name,
|
|
171
172
|
soname,
|
|
172
173
|
allow,
|
|
173
|
-
config
|
|
174
|
+
config,
|
|
175
|
+
...expectedFunctions === void 0 ? {} : { expectedFunctions }
|
|
174
176
|
}))
|
|
175
177
|
}));
|
|
176
178
|
for (const plugin of input.plugins) for (const abi of input.abis) {
|
|
@@ -179,6 +181,7 @@ var buildAndroidApplication = async (input) => {
|
|
|
179
181
|
const destination = (0, node_path.join)(project, "app/src/main/jniLibs", abi, plugin.soname);
|
|
180
182
|
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(destination), { recursive: true });
|
|
181
183
|
await (0, node_fs_promises.copyFile)(library, destination);
|
|
184
|
+
for (const dependency of plugin.dependencies?.[abi] ?? []) await (0, node_fs_promises.copyFile)(dependency, (0, node_path.join)((0, node_path.dirname)(destination), (0, node_path.basename)(dependency)));
|
|
182
185
|
}
|
|
183
186
|
await (0, node_fs_promises.writeFile)((0, node_path.join)(project, "muon-build.json"), JSON.stringify({
|
|
184
187
|
...tools.toolchain,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["spawn","access","delimiter","join","constants","resolve","readFile","dirname","homedir","mkdir","runScriptOnceToText","readFile","resolve","relative","isAbsolute","rm","cp","join","chmod","mkdir","stat","copyFile","writeFile","dirname","pathToFileURL"],"sources":["../../src/command.ts","../../src/toolchain.ts","../../src/build.ts"],"sourcesContent":["// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport { spawn } from 'node:child_process';\n\n/**\n * Runs a build tool without a shell and awaits process completion.\n * @param command - Executable path.\n * @param args - Literal argument vector.\n * @param cwd - Working directory.\n * @param environment - Child environment, including any external credentials.\n * @param output - Optional progress sink; undefined captures output only.\n * @returns Captured standard output and standard error.\n */\nexport const runAndroidCommand = async (\n command: string,\n args: readonly string[],\n cwd: string,\n environment: NodeJS.ProcessEnv,\n output: ((text: string) => void) | undefined\n): Promise<string> =>\n await new Promise<string>((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n env: environment,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let captured = '';\n const receive = (chunk: Buffer) => {\n const text = chunk.toString();\n captured += text;\n output?.(text);\n };\n child.stdout.on('data', receive);\n child.stderr.on('data', receive);\n child.once('error', reject);\n child.once('close', (code, signal) => {\n if (code === 0) resolve(captured);\n else\n reject(\n new Error(`${command} failed (${signal ?? code}):\\n${captured}`)\n );\n });\n });\n","// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport { constants } from 'node:fs';\nimport { access, mkdir, readFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { delimiter, dirname, join, resolve } from 'node:path';\nimport { runAndroidCommand } from './command.js';\n\n/** Versions fixed by the shipped Android component set. */\nexport interface MuonAndroidToolchain {\n /** Exact Android SDK platform package directory. */ readonly platform: string;\n /** Component schema. */ readonly schemaVersion: 1;\n /** Android Gradle plugin version. */ readonly agp: string;\n /** Wrapper version. */ readonly gradle: string;\n /** API used for compilation. */ readonly compileSdk: number;\n /** API targeted by generated applications. */ readonly targetSdk: number;\n /** Minimum installation API; see documented verification range. */ readonly minSdk: number;\n /** Required SDK Build Tools version. */ readonly buildTools: string;\n /** Minimum JDK runtime version. */ readonly javaMin: number;\n /** Highest supported JDK runtime version. */ readonly javaMax: number;\n /** Version of dev.muon:runtime. */ readonly runtimeVersion: string;\n /** ABIs included in the standard runtime. */ readonly abis: readonly string[];\n}\n\n/** Inputs for the Android environment diagnostic. */\nexport interface MuonAndroidPrepareOptions {\n /** Directory containing templates, maven, renderer and toolchain.json. */ componentsDirectory: string;\n /** Explicit SDK location, otherwise resolved from the environment or adb. */ sdkPath:\n string | undefined;\n /** Child environment. */ environment: NodeJS.ProcessEnv;\n /** Whether to download/verify the pinned Gradle distribution using its Wrapper. */ prepareGradle: boolean;\n}\n\n/** Validated tools for an Android build; no NDK or CMake is needed. */\nexport interface MuonAndroidPrepareResult {\n /** Discriminates Android from desktop preparation. */ readonly target: 'android';\n /** Absolute SDK directory. */ readonly sdkPath: string;\n /** Detected JDK major version. */ readonly javaVersion: number;\n /** Absolute Java executable. */ readonly javaPath: string;\n /** Shipped version requirements. */ readonly toolchain: MuonAndroidToolchain;\n /** Component directory used for this build. */ readonly componentsDirectory: string;\n}\n\nconst accessible = async (path: string, mode: number): Promise<boolean> => {\n try {\n await access(path, mode);\n return true;\n } catch {\n return false;\n }\n};\n\nconst findExecutable = async (\n name: string,\n environment: NodeJS.ProcessEnv\n): Promise<string | undefined> => {\n for (const directory of (environment.PATH ?? '')\n .split(delimiter)\n .filter(Boolean)) {\n const path = join(directory, name);\n if (await accessible(path, constants.X_OK)) return path;\n }\n return undefined;\n};\n\n/**\n * Diagnoses a Linux x64 SDK/JDK installation and optionally prepares Gradle.\n * @param options - Component location, SDK override and process environment.\n * @returns Validated tool paths and pinned versions.\n * @remarks Does not install SDK packages, accept licenses, or require a device.\n */\nexport const prepareAndroid = async (\n options: MuonAndroidPrepareOptions\n): Promise<MuonAndroidPrepareResult> => {\n if (process.platform !== 'linux' || process.arch !== 'x64') {\n throw new Error('Android builds currently support Linux x64 hosts.');\n }\n const componentsDirectory = resolve(options.componentsDirectory);\n const toolchain = JSON.parse(\n await readFile(join(componentsDirectory, 'toolchain.json'), 'utf8')\n ) as MuonAndroidToolchain;\n if (toolchain.schemaVersion !== 1)\n throw new Error('Unsupported Muon Android toolchain schema.');\n const adb = await findExecutable('adb', options.environment);\n const candidate =\n options.sdkPath ??\n options.environment.ANDROID_HOME ??\n options.environment.ANDROID_SDK_ROOT ??\n (adb === undefined ? undefined : dirname(dirname(adb)));\n if (!candidate)\n throw new Error(\n 'Android SDK not found. Set ANDROID_HOME or android.sdkPath.'\n );\n const sdkPath = resolve(candidate);\n for (const [file, packageName] of [\n [\n `platforms/${toolchain.platform}/android.jar`,\n `platforms;${toolchain.platform}`,\n ],\n ...['aapt2', 'zipalign', 'apksigner'].map((name) => [\n `build-tools/${toolchain.buildTools}/${name}`,\n `build-tools;${toolchain.buildTools}`,\n ]),\n ]) {\n if (!(await accessible(join(sdkPath, file!), constants.R_OK))) {\n throw new Error(\n `Android SDK ${sdkPath} is missing ${packageName}. Install this package using the Android CLI: android sdk install '${packageName}'. See https://developer.android.com/tools/agents/android-cli/commands/sdk`\n );\n }\n }\n const platformProperties = await readFile(\n join(sdkPath, 'platforms', toolchain.platform, 'source.properties'),\n 'utf8'\n );\n if (\n Number(\n /^AndroidVersion.ApiLevel\\s*=\\s*(\\S+)/mu.exec(platformProperties)?.[1]\n ) !== toolchain.compileSdk\n ) {\n throw new Error(\n `Android SDK platform version differs from the required API ${toolchain.compileSdk}: ${sdkPath}`\n );\n }\n const buildProperties = await readFile(\n join(sdkPath, 'build-tools', toolchain.buildTools, 'source.properties'),\n 'utf8'\n );\n if (\n /^Pkg.Revision\\s*=\\s*(\\S+)/mu.exec(buildProperties)?.[1] !==\n toolchain.buildTools\n ) {\n throw new Error(\n `Android SDK Build Tools version differs from ${toolchain.buildTools}: ${sdkPath}`\n );\n }\n const javaPath = options.environment.JAVA_HOME\n ? join(options.environment.JAVA_HOME, 'bin/java')\n : await findExecutable('java', options.environment);\n if (!javaPath || !(await accessible(javaPath, constants.X_OK))) {\n throw new Error(\n `JDK ${toolchain.javaMin}–${toolchain.javaMax} is required. Set JAVA_HOME or add java to PATH.`\n );\n }\n const versionText = await runAndroidCommand(\n javaPath,\n ['-version'],\n componentsDirectory,\n options.environment,\n undefined\n );\n const javaVersion = Number(\n /(?:openjdk|java) version \"(\\d+)[.\"]/u.exec(versionText)?.[1]\n );\n if (\n !Number.isInteger(javaVersion) ||\n javaVersion < toolchain.javaMin ||\n javaVersion > toolchain.javaMax\n ) {\n throw new Error(\n `JDK ${toolchain.javaMin}–${toolchain.javaMax} is required; detected ${versionText.trim()}.`\n );\n }\n if (options.prepareGradle) {\n const cache = join(homedir(), '.cache/muon/android', toolchain.gradle);\n await mkdir(cache, { recursive: true });\n const result = await runAndroidCommand(\n join(componentsDirectory, 'templates/gradlew'),\n ['--version'],\n cache,\n options.environment,\n undefined\n );\n if (!result.includes(`Gradle ${toolchain.gradle}`))\n throw new Error(\n 'Gradle Wrapper version differs from the shipped toolchain.'\n );\n }\n return {\n target: 'android',\n sdkPath,\n javaVersion,\n javaPath,\n toolchain,\n componentsDirectory,\n };\n};\n","// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport {\n chmod,\n copyFile,\n cp,\n mkdir,\n readFile,\n rm,\n stat,\n writeFile,\n} from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { runScriptOnceToText, type FunCityLogEntry } from 'funcity';\nimport { runAndroidCommand } from './command.js';\nimport { prepareAndroid } from './toolchain.js';\n\n/** ABI shipped by the Muon Android runtime. */\nexport type MuonAndroidAbi = 'arm64-v8a' | 'x86_64';\n\n/** Normalized package-owned plugin entry. */\nexport interface MuonAndroidPackagedPlugin {\n /** Logical capability name. */ readonly name: string;\n /** Packaged ELF soname. */ readonly soname: string;\n /** Explicitly allowed public function patterns. */ readonly allow: readonly string[];\n /** Application-owned plugin configuration. */ readonly config: readonly {\n readonly key: string;\n readonly value: string;\n }[];\n /** Absolute prebuilt library path for each selected ABI. */ readonly libraries: Readonly<\n Partial<Record<MuonAndroidAbi, string>>\n >;\n}\n\n/** Explicit inputs used by the Android package builder. */\nexport interface MuonAndroidApplicationInput {\n /** Packaged Muon Android components. */ componentsDirectory: string;\n /** Directory containing previously built web assets. */ assetsDirectory: string;\n /** Relative URL path prefix under the trusted asset host. */ assetPath: string;\n /** Trusted HTTPS entry URL. */ startPage: string;\n /** Application identifier independent of Muon's Java namespace. */ applicationId: string;\n /** Launcher label. */ label: string;\n /** Monotonic Android update number. */ versionCode: number;\n /** User-facing version. */ versionName: string;\n /** Selected runtime ABIs. */ abis: readonly MuonAndroidAbi[];\n /** Manifest permissions, already normalized by the public build boundary. */ permissions: readonly string[];\n /** Values returned by muon.environments.getConfigValues. */ values: Readonly<\n Record<string, string>\n >;\n /** Explicit prebuilt plugins; an empty array builds a standard app. */ plugins: readonly MuonAndroidPackagedPlugin[];\n /** Optional PNG icon already converted by the public build boundary. */ icon:\n string | undefined;\n /** Owned directory for generated Gradle sources and intermediates. */ projectDirectory: string;\n /** Destination for APKs and result metadata. */ outputDirectory: string;\n /** SDK override. */ sdkPath: string | undefined;\n /** Debug package or unsigned release package. */ variant:\n 'debug' | 'release';\n /** Process environment. */ environment: NodeJS.ProcessEnv;\n /** Progress sink, or undefined for a quiet build. */ output:\n ((text: string) => void) | undefined;\n}\n\n/** Android APK result, without desktop launcher or CEF fields. */\nexport interface MuonAndroidApplicationResult {\n /** Target discriminator. */ readonly target: 'android';\n /** Absolute APK path. */ readonly packagePath: string;\n /** Generated Gradle project for diagnostics. */ readonly projectDirectory: string;\n /** Android variant. */ readonly variant: 'debug' | 'release';\n /** Included native ABIs. */ readonly abis: readonly MuonAndroidAbi[];\n /** Application identifier. */ readonly applicationId: string;\n /** Update version. */ readonly versionCode: number;\n /** Display version. */ readonly versionName: string;\n /** Actual signing state. */ readonly signing:\n 'debug' | 'unsigned' | 'release';\n}\n\nconst xml = (value: string): string =>\n value\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n\nconst render = async (\n template: string,\n variables: ReadonlyMap<string, unknown>\n): Promise<string> => {\n const logs: FunCityLogEntry[] = [];\n const value = await runScriptOnceToText(await readFile(template, 'utf8'), {\n sourceId: template,\n variables,\n logs,\n });\n if (value === undefined || logs.some((log) => log.type === 'error')) {\n throw new Error(\n `Cannot render Android template ${template}: ${JSON.stringify(logs)}`\n );\n }\n return value;\n};\n\n/**\n * Builds a self-contained APK from the shipped AAR and prebuilt web assets.\n * @param input - Explicit application, artifact and toolchain inputs.\n * @returns The APK path and its actual variant/signing state.\n * @remarks Does not run Vite, compile native code or infer a repository root.\n */\nexport const buildAndroidApplication = async (\n input: MuonAndroidApplicationInput\n): Promise<MuonAndroidApplicationResult> => {\n const tools = await prepareAndroid({\n componentsDirectory: input.componentsDirectory,\n sdkPath: input.sdkPath,\n environment: input.environment,\n prepareGradle: false,\n });\n const project = resolve(input.projectDirectory);\n const assetRelative = relative(resolve(input.assetsDirectory), project);\n if (\n assetRelative === '' ||\n (!assetRelative.startsWith('..') && !isAbsolute(assetRelative))\n ) {\n throw new Error(\n 'The generated Android project must be outside the web assets directory.'\n );\n }\n if (\n isAbsolute(input.assetPath) ||\n input.assetPath\n .split(/[\\\\/]/u)\n .some((part) => part === '..' || part === 'muon')\n ) {\n throw new Error(\n 'Android assetPath must be relative and must not use the reserved muon directory.'\n );\n }\n await rm(project, { recursive: true, force: true });\n await cp(join(tools.componentsDirectory, 'templates'), project, {\n recursive: true,\n });\n await chmod(join(project, 'gradlew'), 0o755);\n const assets = join(project, 'app/src/main/assets');\n await mkdir(assets, { recursive: true });\n await cp(input.assetsDirectory, join(assets, input.assetPath), {\n recursive: true,\n dereference: true,\n });\n const frameworkAssets = join(assets, 'muon');\n try {\n await stat(frameworkAssets);\n throw new Error('Web assets must not contain the reserved muon directory.');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n await mkdir(frameworkAssets, { recursive: true });\n await cp(\n join(tools.componentsDirectory, 'licenses'),\n join(frameworkAssets, 'licenses'),\n { recursive: true }\n );\n await copyFile(\n join(tools.componentsDirectory, 'renderer/renderer.js'),\n join(frameworkAssets, 'renderer.js')\n );\n await writeFile(\n join(frameworkAssets, 'config.json'),\n JSON.stringify({ startPage: input.startPage, values: input.values })\n );\n await writeFile(\n join(frameworkAssets, 'plugins.json'),\n JSON.stringify({\n schemaVersion: 1,\n plugins: input.plugins.map(({ name, soname, allow, config }) => ({\n name,\n soname,\n allow,\n config,\n })),\n })\n );\n for (const plugin of input.plugins) {\n for (const abi of input.abis) {\n const library = plugin.libraries[abi];\n if (!library)\n throw new Error(`${plugin.name} is missing its ${abi} library.`);\n const destination = join(\n project,\n 'app/src/main/jniLibs',\n abi,\n plugin.soname\n );\n await mkdir(dirname(destination), { recursive: true });\n await copyFile(library, destination);\n }\n }\n await writeFile(\n join(project, 'muon-build.json'),\n JSON.stringify(\n {\n ...tools.toolchain,\n applicationId: input.applicationId,\n versionCode: input.versionCode,\n versionName: input.versionName,\n abis: input.abis,\n maven: pathToFileURL(join(tools.componentsDirectory, 'maven')).href,\n },\n null,\n 2\n )\n );\n await writeFile(\n join(project, 'app/src/main/AndroidManifest.xml'),\n await render(\n join(project, 'AndroidManifest.xml.fc'),\n new Map([['permissions', input.permissions.map(xml)]])\n )\n );\n const resources = join(project, 'app/src/main/res');\n await mkdir(join(resources, 'values'), { recursive: true });\n await writeFile(\n join(resources, 'values/strings.xml'),\n await render(\n join(project, 'strings.xml.fc'),\n new Map([\n [\n 'label',\n xml(input.label.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')),\n ],\n ])\n )\n );\n if (input.icon !== undefined) {\n await rm(join(resources, 'mipmap/ic_launcher.xml'));\n await copyFile(input.icon, join(resources, 'mipmap/ic_launcher.png'));\n }\n await runAndroidCommand(\n join(project, 'gradlew'),\n [\n '--no-daemon',\n '--console=plain',\n input.variant === 'debug' ? ':app:assembleDebug' : ':app:assembleRelease',\n ],\n project,\n {\n ...input.environment,\n ANDROID_HOME: tools.sdkPath,\n ANDROID_SDK_ROOT: tools.sdkPath,\n },\n input.output\n );\n const name =\n input.variant === 'debug' ? 'app-debug.apk' : 'app-release-unsigned.apk';\n const packagePath = join(\n resolve(input.outputDirectory),\n `${input.applicationId}-${input.versionCode}-${input.variant}.apk`\n );\n await mkdir(dirname(packagePath), { recursive: true });\n await copyFile(\n join(project, 'app/build/outputs/apk', input.variant, name),\n packagePath\n );\n const result: MuonAndroidApplicationResult = {\n target: 'android',\n packagePath,\n projectDirectory: project,\n variant: input.variant,\n abis: input.abis,\n applicationId: input.applicationId,\n versionCode: input.versionCode,\n versionName: input.versionName,\n signing: input.variant === 'debug' ? 'debug' : 'unsigned',\n };\n await writeFile(\n `${packagePath}.json`,\n JSON.stringify(result, null, 2) + '\\n'\n );\n return result;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["spawn","access","delimiter","join","constants","resolve","readFile","dirname","homedir","mkdir","runScriptOnceToText","readFile","resolve","relative","isAbsolute","rm","cp","join","chmod","mkdir","stat","copyFile","writeFile","dirname","basename","pathToFileURL"],"sources":["../../android/command.ts","../../android/toolchain.ts","../../android/build.ts"],"sourcesContent":["// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport { spawn } from \"node:child_process\";\n\n/**\n * Runs a build tool without a shell and awaits process completion.\n * @param command - Executable path.\n * @param args - Literal argument vector.\n * @param cwd - Working directory.\n * @param environment - Child environment, including any external credentials.\n * @param output - Optional progress sink; undefined captures output only.\n * @returns Captured standard output and standard error.\n */\nexport const runAndroidCommand = async (\n command: string,\n args: readonly string[],\n cwd: string,\n environment: NodeJS.ProcessEnv,\n output: ((text: string) => void) | undefined,\n): Promise<string> =>\n await new Promise<string>((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n env: environment,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n let captured = \"\";\n const receive = (chunk: Buffer) => {\n const text = chunk.toString();\n captured += text;\n output?.(text);\n };\n child.stdout.on(\"data\", receive);\n child.stderr.on(\"data\", receive);\n child.once(\"error\", reject);\n child.once(\"close\", (code, signal) => {\n if (code === 0) resolve(captured);\n else\n reject(\n new Error(`${command} failed (${signal ?? code}):\\n${captured}`),\n );\n });\n });\n","// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport { constants } from \"node:fs\";\nimport { access, mkdir, readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { delimiter, dirname, join, resolve } from \"node:path\";\nimport { runAndroidCommand } from \"./command.js\";\n\n/** Versions fixed by the shipped Android component set. */\nexport interface MuonAndroidToolchain {\n /** Exact Android SDK platform package directory. */ readonly platform: string;\n /** Component schema. */ readonly schemaVersion: 1;\n /** Android Gradle plugin version. */ readonly agp: string;\n /** Wrapper version. */ readonly gradle: string;\n /** API used for compilation. */ readonly compileSdk: number;\n /** API targeted by generated applications. */ readonly targetSdk: number;\n /** Minimum installation API; see documented verification range. */ readonly minSdk: number;\n /** Required SDK Build Tools version. */ readonly buildTools: string;\n /** Minimum JDK runtime version. */ readonly javaMin: number;\n /** Highest supported JDK runtime version. */ readonly javaMax: number;\n /** Version of dev.muon:runtime. */ readonly runtimeVersion: string;\n /** ABIs included in the standard runtime. */ readonly abis: readonly string[];\n}\n\n/** Inputs for the Android environment diagnostic. */\nexport interface MuonAndroidPrepareOptions {\n /** Directory containing templates, maven, renderer and toolchain.json. */ componentsDirectory: string;\n /** Explicit SDK location, otherwise resolved from the environment or adb. */ sdkPath:\n string | undefined;\n /** Child environment. */ environment: NodeJS.ProcessEnv;\n /** Whether to download/verify the pinned Gradle distribution using its Wrapper. */ prepareGradle: boolean;\n}\n\n/** Validated tools for an Android build; no NDK or CMake is needed. */\nexport interface MuonAndroidPrepareResult {\n /** Discriminates Android from desktop preparation. */ readonly target: \"android\";\n /** Absolute SDK directory. */ readonly sdkPath: string;\n /** Detected JDK major version. */ readonly javaVersion: number;\n /** Absolute Java executable. */ readonly javaPath: string;\n /** Shipped version requirements. */ readonly toolchain: MuonAndroidToolchain;\n /** Component directory used for this build. */ readonly componentsDirectory: string;\n}\n\nconst accessible = async (path: string, mode: number): Promise<boolean> => {\n try {\n await access(path, mode);\n return true;\n } catch {\n return false;\n }\n};\n\nconst findExecutable = async (\n name: string,\n environment: NodeJS.ProcessEnv,\n): Promise<string | undefined> => {\n for (const directory of (environment.PATH ?? \"\")\n .split(delimiter)\n .filter(Boolean)) {\n const path = join(directory, name);\n if (await accessible(path, constants.X_OK)) return path;\n }\n return undefined;\n};\n\n/**\n * Diagnoses a Linux x64 SDK/JDK installation and optionally prepares Gradle.\n * @param options - Component location, SDK override and process environment.\n * @returns Validated tool paths and pinned versions.\n * @remarks Does not install SDK packages, accept licenses, or require a device.\n */\nexport const prepareAndroid = async (\n options: MuonAndroidPrepareOptions,\n): Promise<MuonAndroidPrepareResult> => {\n if (process.platform !== \"linux\" || process.arch !== \"x64\") {\n throw new Error(\"Android builds currently support Linux x64 hosts.\");\n }\n const componentsDirectory = resolve(options.componentsDirectory);\n const toolchain = JSON.parse(\n await readFile(join(componentsDirectory, \"toolchain.json\"), \"utf8\"),\n ) as MuonAndroidToolchain;\n if (toolchain.schemaVersion !== 1)\n throw new Error(\"Unsupported Muon Android toolchain schema.\");\n const adb = await findExecutable(\"adb\", options.environment);\n const candidate =\n options.sdkPath ??\n options.environment.ANDROID_HOME ??\n options.environment.ANDROID_SDK_ROOT ??\n (adb === undefined ? undefined : dirname(dirname(adb)));\n if (!candidate)\n throw new Error(\n \"Android SDK not found. Set ANDROID_HOME or android.sdkPath.\",\n );\n const sdkPath = resolve(candidate);\n for (const [file, packageName] of [\n [\n `platforms/${toolchain.platform}/android.jar`,\n `platforms;${toolchain.platform}`,\n ],\n ...[\"aapt2\", \"zipalign\", \"apksigner\"].map((name) => [\n `build-tools/${toolchain.buildTools}/${name}`,\n `build-tools;${toolchain.buildTools}`,\n ]),\n ]) {\n if (!(await accessible(join(sdkPath, file!), constants.R_OK))) {\n throw new Error(\n `Android SDK ${sdkPath} is missing ${packageName}. Install this package using the Android CLI: android sdk install '${packageName}'. See https://developer.android.com/tools/agents/android-cli/commands/sdk`,\n );\n }\n }\n const platformProperties = await readFile(\n join(sdkPath, \"platforms\", toolchain.platform, \"source.properties\"),\n \"utf8\",\n );\n if (\n Number(\n /^AndroidVersion.ApiLevel\\s*=\\s*(\\S+)/mu.exec(platformProperties)?.[1],\n ) !== toolchain.compileSdk\n ) {\n throw new Error(\n `Android SDK platform version differs from the required API ${toolchain.compileSdk}: ${sdkPath}`,\n );\n }\n const buildProperties = await readFile(\n join(sdkPath, \"build-tools\", toolchain.buildTools, \"source.properties\"),\n \"utf8\",\n );\n if (\n /^Pkg.Revision\\s*=\\s*(\\S+)/mu.exec(buildProperties)?.[1] !==\n toolchain.buildTools\n ) {\n throw new Error(\n `Android SDK Build Tools version differs from ${toolchain.buildTools}: ${sdkPath}`,\n );\n }\n const javaPath = options.environment.JAVA_HOME\n ? join(options.environment.JAVA_HOME, \"bin/java\")\n : await findExecutable(\"java\", options.environment);\n if (!javaPath || !(await accessible(javaPath, constants.X_OK))) {\n throw new Error(\n `JDK ${toolchain.javaMin}–${toolchain.javaMax} is required. Set JAVA_HOME or add java to PATH.`,\n );\n }\n const versionText = await runAndroidCommand(\n javaPath,\n [\"-version\"],\n componentsDirectory,\n options.environment,\n undefined,\n );\n const javaVersion = Number(\n /(?:openjdk|java) version \"(\\d+)[.\"]/u.exec(versionText)?.[1],\n );\n if (\n !Number.isInteger(javaVersion) ||\n javaVersion < toolchain.javaMin ||\n javaVersion > toolchain.javaMax\n ) {\n throw new Error(\n `JDK ${toolchain.javaMin}–${toolchain.javaMax} is required; detected ${versionText.trim()}.`,\n );\n }\n if (options.prepareGradle) {\n const cache = join(homedir(), \".cache/muon/android\", toolchain.gradle);\n await mkdir(cache, { recursive: true });\n const result = await runAndroidCommand(\n join(componentsDirectory, \"templates/gradlew\"),\n [\"--version\"],\n cache,\n options.environment,\n undefined,\n );\n if (!result.includes(`Gradle ${toolchain.gradle}`))\n throw new Error(\n \"Gradle Wrapper version differs from the shipped toolchain.\",\n );\n }\n return {\n target: \"android\",\n sdkPath,\n javaVersion,\n javaPath,\n toolchain,\n componentsDirectory,\n };\n};\n","// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport {\n chmod,\n copyFile,\n cp,\n mkdir,\n readFile,\n rm,\n stat,\n writeFile,\n} from \"node:fs/promises\";\nimport {\n basename,\n dirname,\n isAbsolute,\n join,\n relative,\n resolve,\n} from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { runScriptOnceToText, type FunCityLogEntry } from \"funcity\";\nimport { runAndroidCommand } from \"./command.js\";\nimport { prepareAndroid } from \"./toolchain.js\";\n\n/** ABI shipped by the Muon Android runtime. */\nexport type MuonAndroidAbi = \"arm64-v8a\" | \"x86_64\";\n\n/** Package-owned plugin exposure and built-in function policy. */\nexport type MuonAndroidPluginAccess = {\n /** Whether the trusted main frame may use the bridge. */ readonly enabled: boolean;\n /** Allowed built-in public function paths. */ readonly internalAllow: readonly string[];\n} & (\n | { /** Global API exposure mode. */ readonly mode: \"simple\" }\n | {\n /** Virtual-module exposure mode. */ readonly mode: \"validate\";\n /** Capabilities generated by the same build as the application bundle. */ readonly capabilities: readonly {\n /** Opaque capability id. */ readonly id: string;\n /** Allowed public function paths. */ readonly allow: readonly string[];\n }[];\n }\n);\n\n/** Normalized package-owned plugin entry. */\nexport interface MuonAndroidPackagedPlugin {\n /** Ordinary shared libraries copied beside the plugin for each ABI. */ readonly dependencies?: Readonly<\n Partial<Record<MuonAndroidAbi, readonly string[]>>\n >;\n /** Logical capability name. */ readonly name: string;\n /** Packaged ELF soname. */ readonly soname: string;\n /** Explicitly allowed public function patterns. */ readonly allow: readonly string[];\n /** Producer catalog after applying the allow policy, checked when loading. */ readonly expectedFunctions?: readonly string[];\n /** Application-owned plugin configuration. */ readonly config: readonly {\n readonly key: string;\n readonly value: string;\n }[];\n /** Absolute prebuilt library path for each selected ABI. */ readonly libraries: Readonly<\n Partial<Record<MuonAndroidAbi, string>>\n >;\n}\n\n/** Explicit inputs used by the Android package builder. */\nexport interface MuonAndroidApplicationInput {\n /** Packaged Muon Android components. */ componentsDirectory: string;\n /** Directory containing previously built web assets. */ assetsDirectory: string;\n /** Relative URL path prefix under the trusted asset host. */ assetPath: string;\n /** Trusted HTTPS entry URL. */ startPage: string;\n /** Application identifier independent of Muon's Java namespace. */ applicationId: string;\n /** Launcher label. */ label: string;\n /** Monotonic Android update number. */ versionCode: number;\n /** User-facing version. */ versionName: string;\n /** Selected runtime ABIs. */ abis: readonly MuonAndroidAbi[];\n /** Manifest permissions, already normalized by the public build boundary. */ permissions: readonly string[];\n /** Values returned by muon.environments.getConfigValues. */ values: Readonly<\n Record<string, string>\n >;\n /** Explicit prebuilt plugins; an empty array builds a standard app. */ plugins: readonly MuonAndroidPackagedPlugin[];\n /** Validated common plugin access settings. */ pluginAccess: MuonAndroidPluginAccess;\n /** Optional PNG icon already converted by the public build boundary. */ icon:\n string | undefined;\n /** Owned directory for generated Gradle sources and intermediates. */ projectDirectory: string;\n /** Destination for APKs and result metadata. */ outputDirectory: string;\n /** SDK override. */ sdkPath: string | undefined;\n /** Debug package or unsigned release package. */ variant:\n \"debug\" | \"release\";\n /** Process environment. */ environment: NodeJS.ProcessEnv;\n /** Progress sink, or undefined for a quiet build. */ output:\n ((text: string) => void) | undefined;\n}\n\n/** Android APK result, without desktop launcher or CEF fields. */\nexport interface MuonAndroidApplicationResult {\n /** Target discriminator. */ readonly target: \"android\";\n /** Absolute APK path. */ readonly packagePath: string;\n /** Generated Gradle project for diagnostics. */ readonly projectDirectory: string;\n /** Android variant. */ readonly variant: \"debug\" | \"release\";\n /** Included native ABIs. */ readonly abis: readonly MuonAndroidAbi[];\n /** Application identifier. */ readonly applicationId: string;\n /** Update version. */ readonly versionCode: number;\n /** Display version. */ readonly versionName: string;\n /** Actual signing state. */ readonly signing:\n \"debug\" | \"unsigned\" | \"release\";\n}\n\nconst xml = (value: string): string =>\n value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n\nconst render = async (\n template: string,\n variables: ReadonlyMap<string, unknown>,\n): Promise<string> => {\n const logs: FunCityLogEntry[] = [];\n const value = await runScriptOnceToText(await readFile(template, \"utf8\"), {\n sourceId: template,\n variables,\n logs,\n });\n if (value === undefined || logs.some((log) => log.type === \"error\")) {\n throw new Error(\n `Cannot render Android template ${template}: ${JSON.stringify(logs)}`,\n );\n }\n return value;\n};\n\n/**\n * Builds a self-contained APK from the shipped AAR and prebuilt web assets.\n * @param input - Explicit application, artifact and toolchain inputs.\n * @returns The APK path and its actual variant/signing state.\n * @remarks Does not run Vite, compile native code or infer a repository root.\n */\nexport const buildAndroidApplication = async (\n input: MuonAndroidApplicationInput,\n): Promise<MuonAndroidApplicationResult> => {\n const tools = await prepareAndroid({\n componentsDirectory: input.componentsDirectory,\n sdkPath: input.sdkPath,\n environment: input.environment,\n prepareGradle: false,\n });\n const project = resolve(input.projectDirectory);\n const assetRelative = relative(resolve(input.assetsDirectory), project);\n if (\n assetRelative === \"\" ||\n (!assetRelative.startsWith(\"..\") && !isAbsolute(assetRelative))\n ) {\n throw new Error(\n \"The generated Android project must be outside the web assets directory.\",\n );\n }\n if (\n isAbsolute(input.assetPath) ||\n input.assetPath\n .split(/[\\\\/]/u)\n .some((part) => part === \"..\" || part === \"muon\")\n ) {\n throw new Error(\n \"Android assetPath must be relative and must not use the reserved muon directory.\",\n );\n }\n await rm(project, { recursive: true, force: true });\n await cp(join(tools.componentsDirectory, \"templates\"), project, {\n recursive: true,\n });\n await chmod(join(project, \"gradlew\"), 0o755);\n const assets = join(project, \"app/src/main/assets\");\n await mkdir(assets, { recursive: true });\n await cp(input.assetsDirectory, join(assets, input.assetPath), {\n recursive: true,\n dereference: true,\n });\n const frameworkAssets = join(assets, \"muon\");\n try {\n await stat(frameworkAssets);\n throw new Error(\"Web assets must not contain the reserved muon directory.\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n await mkdir(frameworkAssets, { recursive: true });\n await cp(\n join(tools.componentsDirectory, \"licenses\"),\n join(frameworkAssets, \"licenses\"),\n { recursive: true },\n );\n await copyFile(\n join(tools.componentsDirectory, \"renderer/renderer.js\"),\n join(frameworkAssets, \"renderer.js\"),\n );\n await writeFile(\n join(frameworkAssets, \"config.json\"),\n JSON.stringify({\n startPage: input.startPage,\n values: input.values,\n plugin: input.pluginAccess,\n }),\n );\n await writeFile(\n join(frameworkAssets, \"plugins.json\"),\n JSON.stringify({\n schemaVersion: 1,\n plugins: input.plugins.map(\n ({ name, soname, allow, config, expectedFunctions }) => ({\n name,\n soname,\n allow,\n config,\n ...(expectedFunctions === undefined ? {} : { expectedFunctions }),\n }),\n ),\n }),\n );\n for (const plugin of input.plugins) {\n for (const abi of input.abis) {\n const library = plugin.libraries[abi];\n if (!library)\n throw new Error(`${plugin.name} is missing its ${abi} library.`);\n const destination = join(\n project,\n \"app/src/main/jniLibs\",\n abi,\n plugin.soname,\n );\n await mkdir(dirname(destination), { recursive: true });\n await copyFile(library, destination);\n for (const dependency of plugin.dependencies?.[abi] ?? [])\n await copyFile(\n dependency,\n join(dirname(destination), basename(dependency)),\n );\n }\n }\n await writeFile(\n join(project, \"muon-build.json\"),\n JSON.stringify(\n {\n ...tools.toolchain,\n applicationId: input.applicationId,\n versionCode: input.versionCode,\n versionName: input.versionName,\n abis: input.abis,\n maven: pathToFileURL(join(tools.componentsDirectory, \"maven\")).href,\n },\n null,\n 2,\n ),\n );\n await writeFile(\n join(project, \"app/src/main/AndroidManifest.xml\"),\n await render(\n join(project, \"AndroidManifest.xml.fc\"),\n new Map([[\"permissions\", input.permissions.map(xml)]]),\n ),\n );\n const resources = join(project, \"app/src/main/res\");\n await mkdir(join(resources, \"values\"), { recursive: true });\n await writeFile(\n join(resources, \"values/strings.xml\"),\n await render(\n join(project, \"strings.xml.fc\"),\n new Map([\n [\n \"label\",\n xml(input.label.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"')),\n ],\n ]),\n ),\n );\n if (input.icon !== undefined) {\n await rm(join(resources, \"mipmap/ic_launcher.xml\"));\n await copyFile(input.icon, join(resources, \"mipmap/ic_launcher.png\"));\n }\n await runAndroidCommand(\n join(project, \"gradlew\"),\n [\n \"--no-daemon\",\n \"--console=plain\",\n input.variant === \"debug\" ? \":app:assembleDebug\" : \":app:assembleRelease\",\n ],\n project,\n {\n ...input.environment,\n ANDROID_HOME: tools.sdkPath,\n ANDROID_SDK_ROOT: tools.sdkPath,\n },\n input.output,\n );\n const name =\n input.variant === \"debug\" ? \"app-debug.apk\" : \"app-release-unsigned.apk\";\n const packagePath = join(\n resolve(input.outputDirectory),\n `${input.applicationId}-${input.versionCode}-${input.variant}.apk`,\n );\n await mkdir(dirname(packagePath), { recursive: true });\n await copyFile(\n join(project, \"app/build/outputs/apk\", input.variant, name),\n packagePath,\n );\n const result: MuonAndroidApplicationResult = {\n target: \"android\",\n packagePath,\n projectDirectory: project,\n variant: input.variant,\n abis: input.abis,\n applicationId: input.applicationId,\n versionCode: input.versionCode,\n versionName: input.versionName,\n signing: input.variant === \"debug\" ? \"debug\" : \"unsigned\",\n };\n await writeFile(\n `${packagePath}.json`,\n JSON.stringify(result, null, 2) + \"\\n\",\n );\n return result;\n};\n"],"mappings":"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"}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* name: muon-
|
|
3
|
-
* version: 0.26.
|
|
4
|
-
* description:
|
|
2
|
+
* name: muon-ui
|
|
3
|
+
* version: 0.26.47
|
|
4
|
+
* description: A multi-platform GUI application framework that uses CEF as its backend
|
|
5
5
|
* author: Kouji Matsui (@kekyo@mi.kekyo.net)
|
|
6
6
|
* license: MIT
|
|
7
7
|
* repository.url: https://github.com/kekyo/muon-ui.git
|
|
8
|
-
* git.commit.hash:
|
|
8
|
+
* git.commit.hash: 95dc2712686873c8a022483fd9abf18598019bd7
|
|
9
9
|
*/
|
|
10
10
|
import { access, chmod, copyFile, cp, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";
|
|
11
|
-
import { delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
11
|
+
import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
12
12
|
import { pathToFileURL } from "node:url";
|
|
13
13
|
import { runScriptOnceToText } from "funcity";
|
|
14
14
|
import { spawn } from "node:child_process";
|
|
15
15
|
import { constants } from "node:fs";
|
|
16
16
|
import { homedir } from "node:os";
|
|
17
|
-
//#region
|
|
17
|
+
//#region android/command.ts
|
|
18
18
|
/**
|
|
19
19
|
* Runs a build tool without a shell and awaits process completion.
|
|
20
20
|
* @param command - Executable path.
|
|
@@ -49,7 +49,7 @@ var runAndroidCommand = async (command, args, cwd, environment, output) => await
|
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
51
|
//#endregion
|
|
52
|
-
//#region
|
|
52
|
+
//#region android/toolchain.ts
|
|
53
53
|
var accessible = async (path, mode) => {
|
|
54
54
|
try {
|
|
55
55
|
await access(path, mode);
|
|
@@ -108,7 +108,7 @@ var prepareAndroid = async (options) => {
|
|
|
108
108
|
};
|
|
109
109
|
};
|
|
110
110
|
//#endregion
|
|
111
|
-
//#region
|
|
111
|
+
//#region android/build.ts
|
|
112
112
|
var xml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
113
113
|
var render = async (template, variables) => {
|
|
114
114
|
const logs = [];
|
|
@@ -161,15 +161,17 @@ var buildAndroidApplication = async (input) => {
|
|
|
161
161
|
await copyFile(join(tools.componentsDirectory, "renderer/renderer.js"), join(frameworkAssets, "renderer.js"));
|
|
162
162
|
await writeFile(join(frameworkAssets, "config.json"), JSON.stringify({
|
|
163
163
|
startPage: input.startPage,
|
|
164
|
-
values: input.values
|
|
164
|
+
values: input.values,
|
|
165
|
+
plugin: input.pluginAccess
|
|
165
166
|
}));
|
|
166
167
|
await writeFile(join(frameworkAssets, "plugins.json"), JSON.stringify({
|
|
167
168
|
schemaVersion: 1,
|
|
168
|
-
plugins: input.plugins.map(({ name, soname, allow, config }) => ({
|
|
169
|
+
plugins: input.plugins.map(({ name, soname, allow, config, expectedFunctions }) => ({
|
|
169
170
|
name,
|
|
170
171
|
soname,
|
|
171
172
|
allow,
|
|
172
|
-
config
|
|
173
|
+
config,
|
|
174
|
+
...expectedFunctions === void 0 ? {} : { expectedFunctions }
|
|
173
175
|
}))
|
|
174
176
|
}));
|
|
175
177
|
for (const plugin of input.plugins) for (const abi of input.abis) {
|
|
@@ -178,6 +180,7 @@ var buildAndroidApplication = async (input) => {
|
|
|
178
180
|
const destination = join(project, "app/src/main/jniLibs", abi, plugin.soname);
|
|
179
181
|
await mkdir(dirname(destination), { recursive: true });
|
|
180
182
|
await copyFile(library, destination);
|
|
183
|
+
for (const dependency of plugin.dependencies?.[abi] ?? []) await copyFile(dependency, join(dirname(destination), basename(dependency)));
|
|
181
184
|
}
|
|
182
185
|
await writeFile(join(project, "muon-build.json"), JSON.stringify({
|
|
183
186
|
...tools.toolchain,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/command.ts","../../src/toolchain.ts","../../src/build.ts"],"sourcesContent":["// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport { spawn } from 'node:child_process';\n\n/**\n * Runs a build tool without a shell and awaits process completion.\n * @param command - Executable path.\n * @param args - Literal argument vector.\n * @param cwd - Working directory.\n * @param environment - Child environment, including any external credentials.\n * @param output - Optional progress sink; undefined captures output only.\n * @returns Captured standard output and standard error.\n */\nexport const runAndroidCommand = async (\n command: string,\n args: readonly string[],\n cwd: string,\n environment: NodeJS.ProcessEnv,\n output: ((text: string) => void) | undefined\n): Promise<string> =>\n await new Promise<string>((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n env: environment,\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n let captured = '';\n const receive = (chunk: Buffer) => {\n const text = chunk.toString();\n captured += text;\n output?.(text);\n };\n child.stdout.on('data', receive);\n child.stderr.on('data', receive);\n child.once('error', reject);\n child.once('close', (code, signal) => {\n if (code === 0) resolve(captured);\n else\n reject(\n new Error(`${command} failed (${signal ?? code}):\\n${captured}`)\n );\n });\n });\n","// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport { constants } from 'node:fs';\nimport { access, mkdir, readFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { delimiter, dirname, join, resolve } from 'node:path';\nimport { runAndroidCommand } from './command.js';\n\n/** Versions fixed by the shipped Android component set. */\nexport interface MuonAndroidToolchain {\n /** Exact Android SDK platform package directory. */ readonly platform: string;\n /** Component schema. */ readonly schemaVersion: 1;\n /** Android Gradle plugin version. */ readonly agp: string;\n /** Wrapper version. */ readonly gradle: string;\n /** API used for compilation. */ readonly compileSdk: number;\n /** API targeted by generated applications. */ readonly targetSdk: number;\n /** Minimum installation API; see documented verification range. */ readonly minSdk: number;\n /** Required SDK Build Tools version. */ readonly buildTools: string;\n /** Minimum JDK runtime version. */ readonly javaMin: number;\n /** Highest supported JDK runtime version. */ readonly javaMax: number;\n /** Version of dev.muon:runtime. */ readonly runtimeVersion: string;\n /** ABIs included in the standard runtime. */ readonly abis: readonly string[];\n}\n\n/** Inputs for the Android environment diagnostic. */\nexport interface MuonAndroidPrepareOptions {\n /** Directory containing templates, maven, renderer and toolchain.json. */ componentsDirectory: string;\n /** Explicit SDK location, otherwise resolved from the environment or adb. */ sdkPath:\n string | undefined;\n /** Child environment. */ environment: NodeJS.ProcessEnv;\n /** Whether to download/verify the pinned Gradle distribution using its Wrapper. */ prepareGradle: boolean;\n}\n\n/** Validated tools for an Android build; no NDK or CMake is needed. */\nexport interface MuonAndroidPrepareResult {\n /** Discriminates Android from desktop preparation. */ readonly target: 'android';\n /** Absolute SDK directory. */ readonly sdkPath: string;\n /** Detected JDK major version. */ readonly javaVersion: number;\n /** Absolute Java executable. */ readonly javaPath: string;\n /** Shipped version requirements. */ readonly toolchain: MuonAndroidToolchain;\n /** Component directory used for this build. */ readonly componentsDirectory: string;\n}\n\nconst accessible = async (path: string, mode: number): Promise<boolean> => {\n try {\n await access(path, mode);\n return true;\n } catch {\n return false;\n }\n};\n\nconst findExecutable = async (\n name: string,\n environment: NodeJS.ProcessEnv\n): Promise<string | undefined> => {\n for (const directory of (environment.PATH ?? '')\n .split(delimiter)\n .filter(Boolean)) {\n const path = join(directory, name);\n if (await accessible(path, constants.X_OK)) return path;\n }\n return undefined;\n};\n\n/**\n * Diagnoses a Linux x64 SDK/JDK installation and optionally prepares Gradle.\n * @param options - Component location, SDK override and process environment.\n * @returns Validated tool paths and pinned versions.\n * @remarks Does not install SDK packages, accept licenses, or require a device.\n */\nexport const prepareAndroid = async (\n options: MuonAndroidPrepareOptions\n): Promise<MuonAndroidPrepareResult> => {\n if (process.platform !== 'linux' || process.arch !== 'x64') {\n throw new Error('Android builds currently support Linux x64 hosts.');\n }\n const componentsDirectory = resolve(options.componentsDirectory);\n const toolchain = JSON.parse(\n await readFile(join(componentsDirectory, 'toolchain.json'), 'utf8')\n ) as MuonAndroidToolchain;\n if (toolchain.schemaVersion !== 1)\n throw new Error('Unsupported Muon Android toolchain schema.');\n const adb = await findExecutable('adb', options.environment);\n const candidate =\n options.sdkPath ??\n options.environment.ANDROID_HOME ??\n options.environment.ANDROID_SDK_ROOT ??\n (adb === undefined ? undefined : dirname(dirname(adb)));\n if (!candidate)\n throw new Error(\n 'Android SDK not found. Set ANDROID_HOME or android.sdkPath.'\n );\n const sdkPath = resolve(candidate);\n for (const [file, packageName] of [\n [\n `platforms/${toolchain.platform}/android.jar`,\n `platforms;${toolchain.platform}`,\n ],\n ...['aapt2', 'zipalign', 'apksigner'].map((name) => [\n `build-tools/${toolchain.buildTools}/${name}`,\n `build-tools;${toolchain.buildTools}`,\n ]),\n ]) {\n if (!(await accessible(join(sdkPath, file!), constants.R_OK))) {\n throw new Error(\n `Android SDK ${sdkPath} is missing ${packageName}. Install this package using the Android CLI: android sdk install '${packageName}'. See https://developer.android.com/tools/agents/android-cli/commands/sdk`\n );\n }\n }\n const platformProperties = await readFile(\n join(sdkPath, 'platforms', toolchain.platform, 'source.properties'),\n 'utf8'\n );\n if (\n Number(\n /^AndroidVersion.ApiLevel\\s*=\\s*(\\S+)/mu.exec(platformProperties)?.[1]\n ) !== toolchain.compileSdk\n ) {\n throw new Error(\n `Android SDK platform version differs from the required API ${toolchain.compileSdk}: ${sdkPath}`\n );\n }\n const buildProperties = await readFile(\n join(sdkPath, 'build-tools', toolchain.buildTools, 'source.properties'),\n 'utf8'\n );\n if (\n /^Pkg.Revision\\s*=\\s*(\\S+)/mu.exec(buildProperties)?.[1] !==\n toolchain.buildTools\n ) {\n throw new Error(\n `Android SDK Build Tools version differs from ${toolchain.buildTools}: ${sdkPath}`\n );\n }\n const javaPath = options.environment.JAVA_HOME\n ? join(options.environment.JAVA_HOME, 'bin/java')\n : await findExecutable('java', options.environment);\n if (!javaPath || !(await accessible(javaPath, constants.X_OK))) {\n throw new Error(\n `JDK ${toolchain.javaMin}–${toolchain.javaMax} is required. Set JAVA_HOME or add java to PATH.`\n );\n }\n const versionText = await runAndroidCommand(\n javaPath,\n ['-version'],\n componentsDirectory,\n options.environment,\n undefined\n );\n const javaVersion = Number(\n /(?:openjdk|java) version \"(\\d+)[.\"]/u.exec(versionText)?.[1]\n );\n if (\n !Number.isInteger(javaVersion) ||\n javaVersion < toolchain.javaMin ||\n javaVersion > toolchain.javaMax\n ) {\n throw new Error(\n `JDK ${toolchain.javaMin}–${toolchain.javaMax} is required; detected ${versionText.trim()}.`\n );\n }\n if (options.prepareGradle) {\n const cache = join(homedir(), '.cache/muon/android', toolchain.gradle);\n await mkdir(cache, { recursive: true });\n const result = await runAndroidCommand(\n join(componentsDirectory, 'templates/gradlew'),\n ['--version'],\n cache,\n options.environment,\n undefined\n );\n if (!result.includes(`Gradle ${toolchain.gradle}`))\n throw new Error(\n 'Gradle Wrapper version differs from the shipped toolchain.'\n );\n }\n return {\n target: 'android',\n sdkPath,\n javaVersion,\n javaPath,\n toolchain,\n componentsDirectory,\n };\n};\n","// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport {\n chmod,\n copyFile,\n cp,\n mkdir,\n readFile,\n rm,\n stat,\n writeFile,\n} from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { runScriptOnceToText, type FunCityLogEntry } from 'funcity';\nimport { runAndroidCommand } from './command.js';\nimport { prepareAndroid } from './toolchain.js';\n\n/** ABI shipped by the Muon Android runtime. */\nexport type MuonAndroidAbi = 'arm64-v8a' | 'x86_64';\n\n/** Normalized package-owned plugin entry. */\nexport interface MuonAndroidPackagedPlugin {\n /** Logical capability name. */ readonly name: string;\n /** Packaged ELF soname. */ readonly soname: string;\n /** Explicitly allowed public function patterns. */ readonly allow: readonly string[];\n /** Application-owned plugin configuration. */ readonly config: readonly {\n readonly key: string;\n readonly value: string;\n }[];\n /** Absolute prebuilt library path for each selected ABI. */ readonly libraries: Readonly<\n Partial<Record<MuonAndroidAbi, string>>\n >;\n}\n\n/** Explicit inputs used by the Android package builder. */\nexport interface MuonAndroidApplicationInput {\n /** Packaged Muon Android components. */ componentsDirectory: string;\n /** Directory containing previously built web assets. */ assetsDirectory: string;\n /** Relative URL path prefix under the trusted asset host. */ assetPath: string;\n /** Trusted HTTPS entry URL. */ startPage: string;\n /** Application identifier independent of Muon's Java namespace. */ applicationId: string;\n /** Launcher label. */ label: string;\n /** Monotonic Android update number. */ versionCode: number;\n /** User-facing version. */ versionName: string;\n /** Selected runtime ABIs. */ abis: readonly MuonAndroidAbi[];\n /** Manifest permissions, already normalized by the public build boundary. */ permissions: readonly string[];\n /** Values returned by muon.environments.getConfigValues. */ values: Readonly<\n Record<string, string>\n >;\n /** Explicit prebuilt plugins; an empty array builds a standard app. */ plugins: readonly MuonAndroidPackagedPlugin[];\n /** Optional PNG icon already converted by the public build boundary. */ icon:\n string | undefined;\n /** Owned directory for generated Gradle sources and intermediates. */ projectDirectory: string;\n /** Destination for APKs and result metadata. */ outputDirectory: string;\n /** SDK override. */ sdkPath: string | undefined;\n /** Debug package or unsigned release package. */ variant:\n 'debug' | 'release';\n /** Process environment. */ environment: NodeJS.ProcessEnv;\n /** Progress sink, or undefined for a quiet build. */ output:\n ((text: string) => void) | undefined;\n}\n\n/** Android APK result, without desktop launcher or CEF fields. */\nexport interface MuonAndroidApplicationResult {\n /** Target discriminator. */ readonly target: 'android';\n /** Absolute APK path. */ readonly packagePath: string;\n /** Generated Gradle project for diagnostics. */ readonly projectDirectory: string;\n /** Android variant. */ readonly variant: 'debug' | 'release';\n /** Included native ABIs. */ readonly abis: readonly MuonAndroidAbi[];\n /** Application identifier. */ readonly applicationId: string;\n /** Update version. */ readonly versionCode: number;\n /** Display version. */ readonly versionName: string;\n /** Actual signing state. */ readonly signing:\n 'debug' | 'unsigned' | 'release';\n}\n\nconst xml = (value: string): string =>\n value\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n\nconst render = async (\n template: string,\n variables: ReadonlyMap<string, unknown>\n): Promise<string> => {\n const logs: FunCityLogEntry[] = [];\n const value = await runScriptOnceToText(await readFile(template, 'utf8'), {\n sourceId: template,\n variables,\n logs,\n });\n if (value === undefined || logs.some((log) => log.type === 'error')) {\n throw new Error(\n `Cannot render Android template ${template}: ${JSON.stringify(logs)}`\n );\n }\n return value;\n};\n\n/**\n * Builds a self-contained APK from the shipped AAR and prebuilt web assets.\n * @param input - Explicit application, artifact and toolchain inputs.\n * @returns The APK path and its actual variant/signing state.\n * @remarks Does not run Vite, compile native code or infer a repository root.\n */\nexport const buildAndroidApplication = async (\n input: MuonAndroidApplicationInput\n): Promise<MuonAndroidApplicationResult> => {\n const tools = await prepareAndroid({\n componentsDirectory: input.componentsDirectory,\n sdkPath: input.sdkPath,\n environment: input.environment,\n prepareGradle: false,\n });\n const project = resolve(input.projectDirectory);\n const assetRelative = relative(resolve(input.assetsDirectory), project);\n if (\n assetRelative === '' ||\n (!assetRelative.startsWith('..') && !isAbsolute(assetRelative))\n ) {\n throw new Error(\n 'The generated Android project must be outside the web assets directory.'\n );\n }\n if (\n isAbsolute(input.assetPath) ||\n input.assetPath\n .split(/[\\\\/]/u)\n .some((part) => part === '..' || part === 'muon')\n ) {\n throw new Error(\n 'Android assetPath must be relative and must not use the reserved muon directory.'\n );\n }\n await rm(project, { recursive: true, force: true });\n await cp(join(tools.componentsDirectory, 'templates'), project, {\n recursive: true,\n });\n await chmod(join(project, 'gradlew'), 0o755);\n const assets = join(project, 'app/src/main/assets');\n await mkdir(assets, { recursive: true });\n await cp(input.assetsDirectory, join(assets, input.assetPath), {\n recursive: true,\n dereference: true,\n });\n const frameworkAssets = join(assets, 'muon');\n try {\n await stat(frameworkAssets);\n throw new Error('Web assets must not contain the reserved muon directory.');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n await mkdir(frameworkAssets, { recursive: true });\n await cp(\n join(tools.componentsDirectory, 'licenses'),\n join(frameworkAssets, 'licenses'),\n { recursive: true }\n );\n await copyFile(\n join(tools.componentsDirectory, 'renderer/renderer.js'),\n join(frameworkAssets, 'renderer.js')\n );\n await writeFile(\n join(frameworkAssets, 'config.json'),\n JSON.stringify({ startPage: input.startPage, values: input.values })\n );\n await writeFile(\n join(frameworkAssets, 'plugins.json'),\n JSON.stringify({\n schemaVersion: 1,\n plugins: input.plugins.map(({ name, soname, allow, config }) => ({\n name,\n soname,\n allow,\n config,\n })),\n })\n );\n for (const plugin of input.plugins) {\n for (const abi of input.abis) {\n const library = plugin.libraries[abi];\n if (!library)\n throw new Error(`${plugin.name} is missing its ${abi} library.`);\n const destination = join(\n project,\n 'app/src/main/jniLibs',\n abi,\n plugin.soname\n );\n await mkdir(dirname(destination), { recursive: true });\n await copyFile(library, destination);\n }\n }\n await writeFile(\n join(project, 'muon-build.json'),\n JSON.stringify(\n {\n ...tools.toolchain,\n applicationId: input.applicationId,\n versionCode: input.versionCode,\n versionName: input.versionName,\n abis: input.abis,\n maven: pathToFileURL(join(tools.componentsDirectory, 'maven')).href,\n },\n null,\n 2\n )\n );\n await writeFile(\n join(project, 'app/src/main/AndroidManifest.xml'),\n await render(\n join(project, 'AndroidManifest.xml.fc'),\n new Map([['permissions', input.permissions.map(xml)]])\n )\n );\n const resources = join(project, 'app/src/main/res');\n await mkdir(join(resources, 'values'), { recursive: true });\n await writeFile(\n join(resources, 'values/strings.xml'),\n await render(\n join(project, 'strings.xml.fc'),\n new Map([\n [\n 'label',\n xml(input.label.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')),\n ],\n ])\n )\n );\n if (input.icon !== undefined) {\n await rm(join(resources, 'mipmap/ic_launcher.xml'));\n await copyFile(input.icon, join(resources, 'mipmap/ic_launcher.png'));\n }\n await runAndroidCommand(\n join(project, 'gradlew'),\n [\n '--no-daemon',\n '--console=plain',\n input.variant === 'debug' ? ':app:assembleDebug' : ':app:assembleRelease',\n ],\n project,\n {\n ...input.environment,\n ANDROID_HOME: tools.sdkPath,\n ANDROID_SDK_ROOT: tools.sdkPath,\n },\n input.output\n );\n const name =\n input.variant === 'debug' ? 'app-debug.apk' : 'app-release-unsigned.apk';\n const packagePath = join(\n resolve(input.outputDirectory),\n `${input.applicationId}-${input.versionCode}-${input.variant}.apk`\n );\n await mkdir(dirname(packagePath), { recursive: true });\n await copyFile(\n join(project, 'app/build/outputs/apk', input.variant, name),\n packagePath\n );\n const result: MuonAndroidApplicationResult = {\n target: 'android',\n packagePath,\n projectDirectory: project,\n variant: input.variant,\n abis: input.abis,\n applicationId: input.applicationId,\n versionCode: input.versionCode,\n versionName: input.versionName,\n signing: input.variant === 'debug' ? 'debug' : 'unsigned',\n };\n await writeFile(\n `${packagePath}.json`,\n JSON.stringify(result, null, 2) + '\\n'\n );\n return result;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../android/command.ts","../../android/toolchain.ts","../../android/build.ts"],"sourcesContent":["// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport { spawn } from \"node:child_process\";\n\n/**\n * Runs a build tool without a shell and awaits process completion.\n * @param command - Executable path.\n * @param args - Literal argument vector.\n * @param cwd - Working directory.\n * @param environment - Child environment, including any external credentials.\n * @param output - Optional progress sink; undefined captures output only.\n * @returns Captured standard output and standard error.\n */\nexport const runAndroidCommand = async (\n command: string,\n args: readonly string[],\n cwd: string,\n environment: NodeJS.ProcessEnv,\n output: ((text: string) => void) | undefined,\n): Promise<string> =>\n await new Promise<string>((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n env: environment,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n let captured = \"\";\n const receive = (chunk: Buffer) => {\n const text = chunk.toString();\n captured += text;\n output?.(text);\n };\n child.stdout.on(\"data\", receive);\n child.stderr.on(\"data\", receive);\n child.once(\"error\", reject);\n child.once(\"close\", (code, signal) => {\n if (code === 0) resolve(captured);\n else\n reject(\n new Error(`${command} failed (${signal ?? code}):\\n${captured}`),\n );\n });\n });\n","// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport { constants } from \"node:fs\";\nimport { access, mkdir, readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { delimiter, dirname, join, resolve } from \"node:path\";\nimport { runAndroidCommand } from \"./command.js\";\n\n/** Versions fixed by the shipped Android component set. */\nexport interface MuonAndroidToolchain {\n /** Exact Android SDK platform package directory. */ readonly platform: string;\n /** Component schema. */ readonly schemaVersion: 1;\n /** Android Gradle plugin version. */ readonly agp: string;\n /** Wrapper version. */ readonly gradle: string;\n /** API used for compilation. */ readonly compileSdk: number;\n /** API targeted by generated applications. */ readonly targetSdk: number;\n /** Minimum installation API; see documented verification range. */ readonly minSdk: number;\n /** Required SDK Build Tools version. */ readonly buildTools: string;\n /** Minimum JDK runtime version. */ readonly javaMin: number;\n /** Highest supported JDK runtime version. */ readonly javaMax: number;\n /** Version of dev.muon:runtime. */ readonly runtimeVersion: string;\n /** ABIs included in the standard runtime. */ readonly abis: readonly string[];\n}\n\n/** Inputs for the Android environment diagnostic. */\nexport interface MuonAndroidPrepareOptions {\n /** Directory containing templates, maven, renderer and toolchain.json. */ componentsDirectory: string;\n /** Explicit SDK location, otherwise resolved from the environment or adb. */ sdkPath:\n string | undefined;\n /** Child environment. */ environment: NodeJS.ProcessEnv;\n /** Whether to download/verify the pinned Gradle distribution using its Wrapper. */ prepareGradle: boolean;\n}\n\n/** Validated tools for an Android build; no NDK or CMake is needed. */\nexport interface MuonAndroidPrepareResult {\n /** Discriminates Android from desktop preparation. */ readonly target: \"android\";\n /** Absolute SDK directory. */ readonly sdkPath: string;\n /** Detected JDK major version. */ readonly javaVersion: number;\n /** Absolute Java executable. */ readonly javaPath: string;\n /** Shipped version requirements. */ readonly toolchain: MuonAndroidToolchain;\n /** Component directory used for this build. */ readonly componentsDirectory: string;\n}\n\nconst accessible = async (path: string, mode: number): Promise<boolean> => {\n try {\n await access(path, mode);\n return true;\n } catch {\n return false;\n }\n};\n\nconst findExecutable = async (\n name: string,\n environment: NodeJS.ProcessEnv,\n): Promise<string | undefined> => {\n for (const directory of (environment.PATH ?? \"\")\n .split(delimiter)\n .filter(Boolean)) {\n const path = join(directory, name);\n if (await accessible(path, constants.X_OK)) return path;\n }\n return undefined;\n};\n\n/**\n * Diagnoses a Linux x64 SDK/JDK installation and optionally prepares Gradle.\n * @param options - Component location, SDK override and process environment.\n * @returns Validated tool paths and pinned versions.\n * @remarks Does not install SDK packages, accept licenses, or require a device.\n */\nexport const prepareAndroid = async (\n options: MuonAndroidPrepareOptions,\n): Promise<MuonAndroidPrepareResult> => {\n if (process.platform !== \"linux\" || process.arch !== \"x64\") {\n throw new Error(\"Android builds currently support Linux x64 hosts.\");\n }\n const componentsDirectory = resolve(options.componentsDirectory);\n const toolchain = JSON.parse(\n await readFile(join(componentsDirectory, \"toolchain.json\"), \"utf8\"),\n ) as MuonAndroidToolchain;\n if (toolchain.schemaVersion !== 1)\n throw new Error(\"Unsupported Muon Android toolchain schema.\");\n const adb = await findExecutable(\"adb\", options.environment);\n const candidate =\n options.sdkPath ??\n options.environment.ANDROID_HOME ??\n options.environment.ANDROID_SDK_ROOT ??\n (adb === undefined ? undefined : dirname(dirname(adb)));\n if (!candidate)\n throw new Error(\n \"Android SDK not found. Set ANDROID_HOME or android.sdkPath.\",\n );\n const sdkPath = resolve(candidate);\n for (const [file, packageName] of [\n [\n `platforms/${toolchain.platform}/android.jar`,\n `platforms;${toolchain.platform}`,\n ],\n ...[\"aapt2\", \"zipalign\", \"apksigner\"].map((name) => [\n `build-tools/${toolchain.buildTools}/${name}`,\n `build-tools;${toolchain.buildTools}`,\n ]),\n ]) {\n if (!(await accessible(join(sdkPath, file!), constants.R_OK))) {\n throw new Error(\n `Android SDK ${sdkPath} is missing ${packageName}. Install this package using the Android CLI: android sdk install '${packageName}'. See https://developer.android.com/tools/agents/android-cli/commands/sdk`,\n );\n }\n }\n const platformProperties = await readFile(\n join(sdkPath, \"platforms\", toolchain.platform, \"source.properties\"),\n \"utf8\",\n );\n if (\n Number(\n /^AndroidVersion.ApiLevel\\s*=\\s*(\\S+)/mu.exec(platformProperties)?.[1],\n ) !== toolchain.compileSdk\n ) {\n throw new Error(\n `Android SDK platform version differs from the required API ${toolchain.compileSdk}: ${sdkPath}`,\n );\n }\n const buildProperties = await readFile(\n join(sdkPath, \"build-tools\", toolchain.buildTools, \"source.properties\"),\n \"utf8\",\n );\n if (\n /^Pkg.Revision\\s*=\\s*(\\S+)/mu.exec(buildProperties)?.[1] !==\n toolchain.buildTools\n ) {\n throw new Error(\n `Android SDK Build Tools version differs from ${toolchain.buildTools}: ${sdkPath}`,\n );\n }\n const javaPath = options.environment.JAVA_HOME\n ? join(options.environment.JAVA_HOME, \"bin/java\")\n : await findExecutable(\"java\", options.environment);\n if (!javaPath || !(await accessible(javaPath, constants.X_OK))) {\n throw new Error(\n `JDK ${toolchain.javaMin}–${toolchain.javaMax} is required. Set JAVA_HOME or add java to PATH.`,\n );\n }\n const versionText = await runAndroidCommand(\n javaPath,\n [\"-version\"],\n componentsDirectory,\n options.environment,\n undefined,\n );\n const javaVersion = Number(\n /(?:openjdk|java) version \"(\\d+)[.\"]/u.exec(versionText)?.[1],\n );\n if (\n !Number.isInteger(javaVersion) ||\n javaVersion < toolchain.javaMin ||\n javaVersion > toolchain.javaMax\n ) {\n throw new Error(\n `JDK ${toolchain.javaMin}–${toolchain.javaMax} is required; detected ${versionText.trim()}.`,\n );\n }\n if (options.prepareGradle) {\n const cache = join(homedir(), \".cache/muon/android\", toolchain.gradle);\n await mkdir(cache, { recursive: true });\n const result = await runAndroidCommand(\n join(componentsDirectory, \"templates/gradlew\"),\n [\"--version\"],\n cache,\n options.environment,\n undefined,\n );\n if (!result.includes(`Gradle ${toolchain.gradle}`))\n throw new Error(\n \"Gradle Wrapper version differs from the shipped toolchain.\",\n );\n }\n return {\n target: \"android\",\n sdkPath,\n javaVersion,\n javaPath,\n toolchain,\n componentsDirectory,\n };\n};\n","// muon - Multi-platform GUI application framework that uses CEF as its backend\n// Copyright (c) Kouji Matsui. (@kekyo@mi.kekyo.net)\n// Under MIT.\n// https://github.com/kekyo/muon-ui\n\nimport {\n chmod,\n copyFile,\n cp,\n mkdir,\n readFile,\n rm,\n stat,\n writeFile,\n} from \"node:fs/promises\";\nimport {\n basename,\n dirname,\n isAbsolute,\n join,\n relative,\n resolve,\n} from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { runScriptOnceToText, type FunCityLogEntry } from \"funcity\";\nimport { runAndroidCommand } from \"./command.js\";\nimport { prepareAndroid } from \"./toolchain.js\";\n\n/** ABI shipped by the Muon Android runtime. */\nexport type MuonAndroidAbi = \"arm64-v8a\" | \"x86_64\";\n\n/** Package-owned plugin exposure and built-in function policy. */\nexport type MuonAndroidPluginAccess = {\n /** Whether the trusted main frame may use the bridge. */ readonly enabled: boolean;\n /** Allowed built-in public function paths. */ readonly internalAllow: readonly string[];\n} & (\n | { /** Global API exposure mode. */ readonly mode: \"simple\" }\n | {\n /** Virtual-module exposure mode. */ readonly mode: \"validate\";\n /** Capabilities generated by the same build as the application bundle. */ readonly capabilities: readonly {\n /** Opaque capability id. */ readonly id: string;\n /** Allowed public function paths. */ readonly allow: readonly string[];\n }[];\n }\n);\n\n/** Normalized package-owned plugin entry. */\nexport interface MuonAndroidPackagedPlugin {\n /** Ordinary shared libraries copied beside the plugin for each ABI. */ readonly dependencies?: Readonly<\n Partial<Record<MuonAndroidAbi, readonly string[]>>\n >;\n /** Logical capability name. */ readonly name: string;\n /** Packaged ELF soname. */ readonly soname: string;\n /** Explicitly allowed public function patterns. */ readonly allow: readonly string[];\n /** Producer catalog after applying the allow policy, checked when loading. */ readonly expectedFunctions?: readonly string[];\n /** Application-owned plugin configuration. */ readonly config: readonly {\n readonly key: string;\n readonly value: string;\n }[];\n /** Absolute prebuilt library path for each selected ABI. */ readonly libraries: Readonly<\n Partial<Record<MuonAndroidAbi, string>>\n >;\n}\n\n/** Explicit inputs used by the Android package builder. */\nexport interface MuonAndroidApplicationInput {\n /** Packaged Muon Android components. */ componentsDirectory: string;\n /** Directory containing previously built web assets. */ assetsDirectory: string;\n /** Relative URL path prefix under the trusted asset host. */ assetPath: string;\n /** Trusted HTTPS entry URL. */ startPage: string;\n /** Application identifier independent of Muon's Java namespace. */ applicationId: string;\n /** Launcher label. */ label: string;\n /** Monotonic Android update number. */ versionCode: number;\n /** User-facing version. */ versionName: string;\n /** Selected runtime ABIs. */ abis: readonly MuonAndroidAbi[];\n /** Manifest permissions, already normalized by the public build boundary. */ permissions: readonly string[];\n /** Values returned by muon.environments.getConfigValues. */ values: Readonly<\n Record<string, string>\n >;\n /** Explicit prebuilt plugins; an empty array builds a standard app. */ plugins: readonly MuonAndroidPackagedPlugin[];\n /** Validated common plugin access settings. */ pluginAccess: MuonAndroidPluginAccess;\n /** Optional PNG icon already converted by the public build boundary. */ icon:\n string | undefined;\n /** Owned directory for generated Gradle sources and intermediates. */ projectDirectory: string;\n /** Destination for APKs and result metadata. */ outputDirectory: string;\n /** SDK override. */ sdkPath: string | undefined;\n /** Debug package or unsigned release package. */ variant:\n \"debug\" | \"release\";\n /** Process environment. */ environment: NodeJS.ProcessEnv;\n /** Progress sink, or undefined for a quiet build. */ output:\n ((text: string) => void) | undefined;\n}\n\n/** Android APK result, without desktop launcher or CEF fields. */\nexport interface MuonAndroidApplicationResult {\n /** Target discriminator. */ readonly target: \"android\";\n /** Absolute APK path. */ readonly packagePath: string;\n /** Generated Gradle project for diagnostics. */ readonly projectDirectory: string;\n /** Android variant. */ readonly variant: \"debug\" | \"release\";\n /** Included native ABIs. */ readonly abis: readonly MuonAndroidAbi[];\n /** Application identifier. */ readonly applicationId: string;\n /** Update version. */ readonly versionCode: number;\n /** Display version. */ readonly versionName: string;\n /** Actual signing state. */ readonly signing:\n \"debug\" | \"unsigned\" | \"release\";\n}\n\nconst xml = (value: string): string =>\n value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\");\n\nconst render = async (\n template: string,\n variables: ReadonlyMap<string, unknown>,\n): Promise<string> => {\n const logs: FunCityLogEntry[] = [];\n const value = await runScriptOnceToText(await readFile(template, \"utf8\"), {\n sourceId: template,\n variables,\n logs,\n });\n if (value === undefined || logs.some((log) => log.type === \"error\")) {\n throw new Error(\n `Cannot render Android template ${template}: ${JSON.stringify(logs)}`,\n );\n }\n return value;\n};\n\n/**\n * Builds a self-contained APK from the shipped AAR and prebuilt web assets.\n * @param input - Explicit application, artifact and toolchain inputs.\n * @returns The APK path and its actual variant/signing state.\n * @remarks Does not run Vite, compile native code or infer a repository root.\n */\nexport const buildAndroidApplication = async (\n input: MuonAndroidApplicationInput,\n): Promise<MuonAndroidApplicationResult> => {\n const tools = await prepareAndroid({\n componentsDirectory: input.componentsDirectory,\n sdkPath: input.sdkPath,\n environment: input.environment,\n prepareGradle: false,\n });\n const project = resolve(input.projectDirectory);\n const assetRelative = relative(resolve(input.assetsDirectory), project);\n if (\n assetRelative === \"\" ||\n (!assetRelative.startsWith(\"..\") && !isAbsolute(assetRelative))\n ) {\n throw new Error(\n \"The generated Android project must be outside the web assets directory.\",\n );\n }\n if (\n isAbsolute(input.assetPath) ||\n input.assetPath\n .split(/[\\\\/]/u)\n .some((part) => part === \"..\" || part === \"muon\")\n ) {\n throw new Error(\n \"Android assetPath must be relative and must not use the reserved muon directory.\",\n );\n }\n await rm(project, { recursive: true, force: true });\n await cp(join(tools.componentsDirectory, \"templates\"), project, {\n recursive: true,\n });\n await chmod(join(project, \"gradlew\"), 0o755);\n const assets = join(project, \"app/src/main/assets\");\n await mkdir(assets, { recursive: true });\n await cp(input.assetsDirectory, join(assets, input.assetPath), {\n recursive: true,\n dereference: true,\n });\n const frameworkAssets = join(assets, \"muon\");\n try {\n await stat(frameworkAssets);\n throw new Error(\"Web assets must not contain the reserved muon directory.\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n await mkdir(frameworkAssets, { recursive: true });\n await cp(\n join(tools.componentsDirectory, \"licenses\"),\n join(frameworkAssets, \"licenses\"),\n { recursive: true },\n );\n await copyFile(\n join(tools.componentsDirectory, \"renderer/renderer.js\"),\n join(frameworkAssets, \"renderer.js\"),\n );\n await writeFile(\n join(frameworkAssets, \"config.json\"),\n JSON.stringify({\n startPage: input.startPage,\n values: input.values,\n plugin: input.pluginAccess,\n }),\n );\n await writeFile(\n join(frameworkAssets, \"plugins.json\"),\n JSON.stringify({\n schemaVersion: 1,\n plugins: input.plugins.map(\n ({ name, soname, allow, config, expectedFunctions }) => ({\n name,\n soname,\n allow,\n config,\n ...(expectedFunctions === undefined ? {} : { expectedFunctions }),\n }),\n ),\n }),\n );\n for (const plugin of input.plugins) {\n for (const abi of input.abis) {\n const library = plugin.libraries[abi];\n if (!library)\n throw new Error(`${plugin.name} is missing its ${abi} library.`);\n const destination = join(\n project,\n \"app/src/main/jniLibs\",\n abi,\n plugin.soname,\n );\n await mkdir(dirname(destination), { recursive: true });\n await copyFile(library, destination);\n for (const dependency of plugin.dependencies?.[abi] ?? [])\n await copyFile(\n dependency,\n join(dirname(destination), basename(dependency)),\n );\n }\n }\n await writeFile(\n join(project, \"muon-build.json\"),\n JSON.stringify(\n {\n ...tools.toolchain,\n applicationId: input.applicationId,\n versionCode: input.versionCode,\n versionName: input.versionName,\n abis: input.abis,\n maven: pathToFileURL(join(tools.componentsDirectory, \"maven\")).href,\n },\n null,\n 2,\n ),\n );\n await writeFile(\n join(project, \"app/src/main/AndroidManifest.xml\"),\n await render(\n join(project, \"AndroidManifest.xml.fc\"),\n new Map([[\"permissions\", input.permissions.map(xml)]]),\n ),\n );\n const resources = join(project, \"app/src/main/res\");\n await mkdir(join(resources, \"values\"), { recursive: true });\n await writeFile(\n join(resources, \"values/strings.xml\"),\n await render(\n join(project, \"strings.xml.fc\"),\n new Map([\n [\n \"label\",\n xml(input.label.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"')),\n ],\n ]),\n ),\n );\n if (input.icon !== undefined) {\n await rm(join(resources, \"mipmap/ic_launcher.xml\"));\n await copyFile(input.icon, join(resources, \"mipmap/ic_launcher.png\"));\n }\n await runAndroidCommand(\n join(project, \"gradlew\"),\n [\n \"--no-daemon\",\n \"--console=plain\",\n input.variant === \"debug\" ? \":app:assembleDebug\" : \":app:assembleRelease\",\n ],\n project,\n {\n ...input.environment,\n ANDROID_HOME: tools.sdkPath,\n ANDROID_SDK_ROOT: tools.sdkPath,\n },\n input.output,\n );\n const name =\n input.variant === \"debug\" ? \"app-debug.apk\" : \"app-release-unsigned.apk\";\n const packagePath = join(\n resolve(input.outputDirectory),\n `${input.applicationId}-${input.versionCode}-${input.variant}.apk`,\n );\n await mkdir(dirname(packagePath), { recursive: true });\n await copyFile(\n join(project, \"app/build/outputs/apk\", input.variant, name),\n packagePath,\n );\n const result: MuonAndroidApplicationResult = {\n target: \"android\",\n packagePath,\n projectDirectory: project,\n variant: input.variant,\n abis: input.abis,\n applicationId: input.applicationId,\n versionCode: input.versionCode,\n versionName: input.versionName,\n signing: input.variant === \"debug\" ? \"debug\" : \"unsigned\",\n };\n await writeFile(\n `${packagePath}.json`,\n JSON.stringify(result, null, 2) + \"\\n\",\n );\n return result;\n};\n"],"mappings":"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"}
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
ec2aada440f7f82924173e3e9a8d4898
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
83e540bc7727f775531f4fcdb1110808226ae9bf
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
90bd0cbd4cd0155dbcb227221488527a75222f73d2ca6f17a13f07876947fa3f
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
bbb84b6bbe52de655c11f765aafa4c32ee2f41a8c5854574925cd94a7beed9575b209d93eb015be81d4c1316416ac2bf66c2ebfd304f51ea72222a570bdf1a59
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
{
|
|
36
36
|
"name": "runtime-0.1.0.aar",
|
|
37
37
|
"url": "runtime-0.1.0.aar",
|
|
38
|
-
"size":
|
|
39
|
-
"sha512": "
|
|
40
|
-
"sha256": "
|
|
41
|
-
"sha1": "
|
|
42
|
-
"md5": "
|
|
38
|
+
"size": 1514484,
|
|
39
|
+
"sha512": "bbb84b6bbe52de655c11f765aafa4c32ee2f41a8c5854574925cd94a7beed9575b209d93eb015be81d4c1316416ac2bf66c2ebfd304f51ea72222a570bdf1a59",
|
|
40
|
+
"sha256": "90bd0cbd4cd0155dbcb227221488527a75222f73d2ca6f17a13f07876947fa3f",
|
|
41
|
+
"sha1": "83e540bc7727f775531f4fcdb1110808226ae9bf",
|
|
42
|
+
"md5": "ec2aada440f7f82924173e3e9a8d4898"
|
|
43
43
|
}
|
|
44
44
|
]
|
|
45
45
|
},
|
|
@@ -78,11 +78,11 @@
|
|
|
78
78
|
{
|
|
79
79
|
"name": "runtime-0.1.0.aar",
|
|
80
80
|
"url": "runtime-0.1.0.aar",
|
|
81
|
-
"size":
|
|
82
|
-
"sha512": "
|
|
83
|
-
"sha256": "
|
|
84
|
-
"sha1": "
|
|
85
|
-
"md5": "
|
|
81
|
+
"size": 1514484,
|
|
82
|
+
"sha512": "bbb84b6bbe52de655c11f765aafa4c32ee2f41a8c5854574925cd94a7beed9575b209d93eb015be81d4c1316416ac2bf66c2ebfd304f51ea72222a570bdf1a59",
|
|
83
|
+
"sha256": "90bd0cbd4cd0155dbcb227221488527a75222f73d2ca6f17a13f07876947fa3f",
|
|
84
|
+
"sha1": "83e540bc7727f775531f4fcdb1110808226ae9bf",
|
|
85
|
+
"md5": "ec2aada440f7f82924173e3e9a8d4898"
|
|
86
86
|
}
|
|
87
87
|
]
|
|
88
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
2caeaa47aa8dcf6e50624b478248e365
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
bdde7fec7bfbe6e525a4ef2862fa0ac42adae9e0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
6d545342f96722f52829002ff6c087764f57e96e8ecb1d91e13b4b77a21753d5
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
d99dc7b310fe3b03fdc239edbab862b68e6298a526251e6cc2bc2fc8fc277a3ecc88c4bea5f0e59471f94513159d835d83df3a9438b2cb49baa13d9ec879ccd6
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
1a0231530bbaa768a6ef67192d06eb60
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
f9c1fbf3690b2ed6c67b7c7d1cc6da71541913f9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
edfde4230e7c0d84c574eae6c7e5df4f6587935b6305213bac4b648059bc02ab
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5415dc9cdbd48bc56f7a8474642eed83fd8d20933550c5a8089e202e026a67d0b56f3c96c2a875c22922c36fc90107e51435b8010338848c10d32b579807e30b
|