refactor directory

This commit is contained in:
LiBr
2026-04-10 08:53:51 +08:00
parent 41d3f700b9
commit 8d31144741
215 changed files with 938 additions and 1836 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -16,12 +16,13 @@
"fflate": "^0.8.2",
"jszip": "^3.10.1",
"node-forge": "^1.3.3",
"webmuxd": "file:.."
"webmuxd": "workspace:*"
},
"devDependencies": {
"@tailwindcss/vite": "^4.2.1",
"tailwindcss": "^4.2.1",
"typescript": "~5.9.3",
"vite": "^7.3.1"
}
},
"packageManager": "bun@1.3.11"
}

View File

@@ -1,9 +1,7 @@
import { strFromU8, unzipSync } from "fflate"
import {
AppleAPI,
Fetch,
signIPA,
type AnisetteData,
type AppleAPI,
type AppID,
type Certificate,
type Device,
@@ -82,12 +80,54 @@ export interface AppleSigningWithContextRequest {
onLog: (message: string) => void
}
let appleApiInstance: AppleAPI | null = null
interface AltsignModule {
AppleAPI: new (fetch: unknown) => AppleAPI
Fetch: new (
initLibcurl: typeof import("./anisette-libcurl-init").initLibcurl,
fetcher: (
url: string,
options: {
method?: string
headers?: HeadersInit
body?: BodyInit | null
},
) => Promise<Response>,
) => unknown
signIPA(options: {
ipaData?: Uint8Array
ipaPath?: string
outputPath?: string
certificate: Uint8Array
privateKey: Uint8Array
provisioningProfile: Uint8Array
bundleID?: string
displayName?: string
adhoc?: boolean
forceSign?: boolean
}): Promise<{ data: Uint8Array }>
}
function getAppleApi(): AppleAPI {
let appleApiInstance: AppleAPI | null = null
let altsignModulePromise: Promise<AltsignModule> | null = null
/**
* Keep `altsign.js` and its transitive `zsign-wasm` bundle out of the initial
* Vite module graph. They are only needed after the user starts login/signing.
*/
async function loadAltsignModule(): Promise<AltsignModule> {
if (!altsignModulePromise) {
altsignModulePromise = import("altsign.js").then((moduleValue) => {
return moduleValue as unknown as AltsignModule
})
}
return await altsignModulePromise
}
async function getAppleApi(): Promise<AppleAPI> {
if (appleApiInstance) {
return appleApiInstance
}
const { AppleAPI, Fetch } = await loadAltsignModule()
const appleFetch = new Fetch(initLibcurl, async (url, options) => {
const response = await libcurl.fetch(url, {
method: options.method,
@@ -116,12 +156,12 @@ export async function loginAppleDeveloperAccount(
const log = request.onLog ?? (() => undefined)
log(`Login stage: authenticating Apple account ${maskEmail(appleId)}...`)
const api = getAppleApi()
const api = await getAppleApi()
const { session } = await api.authenticate(
appleId,
password,
request.anisetteData,
(submitCode) => {
(submitCode: (code: string) => void) => {
if (!request.onTwoFactorRequired) {
throw new Error("2FA required but no in-page handler provided")
}
@@ -160,7 +200,7 @@ export async function refreshAppleDeveloperContext(
onLog?: (message: string) => void,
): Promise<AppleDeveloperContext> {
const log = onLog ?? (() => undefined)
const api = getAppleApi()
const api = await getAppleApi()
log("Signing stage: refreshing team/certificates/devices...")
const team = await api.fetchTeam(context.session)
const [certificates, devices] = await Promise.all([
@@ -209,7 +249,7 @@ export async function signIpaWithAppleContext(
throw new Error("Cannot sign IPA: bundle identifier is missing")
}
const api = getAppleApi()
const api = await getAppleApi()
const team = context.team
onLog(`Signing stage: using team ${team.identifier} (${team.name}).`)
@@ -237,6 +277,7 @@ export async function signIpaWithAppleContext(
const provisioningProfile = await api.fetchProvisioningProfile(context.session, team, appId)
onLog("Signing stage: resigning IPA in browser...")
const { signIPA } = await loadAltsignModule()
const signed = await signIPA({
ipaData,
certificate: identity.certificate.publicKey,

View File

@@ -12,10 +12,6 @@ import {
signIpaWithAppleContext,
type AppleDeveloperContext,
} from "./apple-signing"
import initOpensslWasm, {
libimobiledevice_generate_pair_record,
OpensslClient,
} from "../../tls/openssl-wasm/pkg/openssl_wasm.js"
interface WebUsbTransportInstance {
readonly isOpen: boolean
@@ -217,15 +213,31 @@ const webmuxdEncodeStoredPairRecord = resolveWebmuxdExport<
const webmuxdDecodeStoredPairRecord = resolveWebmuxdExport<
(payload: StoredPairRecordPayload) => PairRecord | null
>(webmuxdModuleValue, "decodeStoredPairRecord")
let opensslInitPromise: Promise<void> | null = null
const ensureOpensslReady = async (): Promise<void> => {
if (!opensslInitPromise) {
opensslInitPromise = initOpensslWasm().then(() => undefined)
const webmuxdCreateOpenSslWasmTlsFactory = resolveWebmuxdExport<
() => {
ensureReady?(): Promise<void>
createConnection(request: {
serverName: string
caCertificatePem: string
certificatePem: string
privateKeyPem: string
}): {
is_handshaking(): boolean
write_plaintext(data: Uint8Array): void
feed_tls(data: Uint8Array): void
take_tls_out(): Uint8Array
take_plain_out(): Uint8Array
free(): void
}
}
await opensslInitPromise
}
>(webmuxdModuleValue, "createOpenSslWasmTlsFactory")
const webmuxdGeneratePairRecordWithOpenSslWasm = resolveWebmuxdExport<
(request: {
devicePublicKey: Uint8Array
hostId: string
systemBuid: string
}) => Promise<string>
>(webmuxdModuleValue, "generatePairRecordWithOpenSslWasm")
const app = document.querySelector<HTMLDivElement>("#app")
if (!app) {
@@ -578,17 +590,7 @@ const ensureClientSelected = async (): Promise<DirectUsbMuxClient> => {
log: addLog,
onStateChange: refreshUi,
lockdownLabel: "webmuxd.frontend",
tlsFactory: {
ensureReady: ensureOpensslReady,
createConnection: (request) => {
return new OpensslClient(
request.serverName,
request.caCertificatePem,
request.certificatePem,
request.privateKeyPem,
)
},
},
tlsFactory: webmuxdCreateOpenSslWasmTlsFactory(),
pairRecordFactory: {
createPairRecord: async (request) => {
return await createPairRecord(request.devicePublicKey, request.hostId, request.systemBuid)
@@ -1490,12 +1492,11 @@ async function createPairRecord(
hostId: string,
systemBuid: string,
): Promise<PairRecord> {
await ensureOpensslReady()
const payloadText = libimobiledevice_generate_pair_record(
new Uint8Array(devicePublicKeyBytes),
const payloadText = await webmuxdGeneratePairRecordWithOpenSslWasm({
devicePublicKey: devicePublicKeyBytes,
hostId,
systemBuid,
)
})
const payload = JSON.parse(payloadText) as WasmPairRecordPayload
return {
hostId: payload.hostId,

View File

@@ -17,10 +17,13 @@ export default defineConfig({
},
},
resolve: {
alias: {
webmuxd: resolve(repoRootDir, "dependencies/webmuxd/lib/webmuxd.js"),
},
preserveSymlinks: true,
},
optimizeDeps: {
include: ["webmuxd", "@lbr77/anisette-js/browser"],
include: ["@lbr77/anisette-js/browser"],
},
build: {
commonjsOptions: {