peachsim 0.1.2194 → 0.1.2195
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 +4 -1
- package/cli/commands/control.ts +2 -0
- package/cli/commands/kotlin.ts +10 -3
- package/cli/commands/package.ts +2 -0
- package/cli/native-input.ts +2 -0
- package/cli/outbound-endpoints.ts +1 -1
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/bundle-channel.cjs +986 -785
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/config.mjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +3 -3
- package/dist-lib/expo-swift-metadata.cjs +1 -1
- package/dist-lib/expo-swift-metadata.mjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +991 -790
- package/dist-lib/host/fetch-proxy-handler.cjs +2 -2
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +2 -2
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +82 -13
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +2 -2
- package/dist-lib/native-app-identity-project.cjs +1 -1
- package/dist-lib/native-app-identity-project.mjs +1 -1
- package/dist-lib/native-app-identity.cjs +1 -1
- package/dist-lib/native-app-identity.mjs +1 -1
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/pdfium-raster.cjs +1 -1
- package/dist-lib/pdfium-raster.mjs +1 -1
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/public-origins-lib-esm.json +24 -24
- package/dist-lib/public-origins-lib.json +65 -62
- package/dist-lib/react-native-host-modules.cjs +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/reap-browser.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +1513 -1264
- package/dist-lib/swift-compile.cjs +1 -1
- package/dist-lib/swift-compile.mjs +1 -1
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +1 -1
- package/dist-lib/swift-submit.mjs +1 -1
- package/dist-lib/swift-toolchain.cjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +2 -2
- package/dist-lib/vite.cjs +2 -2
- package/dist-lib/worklet-executable.cjs +1 -1
- package/dist-lib/worklet-executable.mjs +1 -1
- package/dist-types/packages/peach-engine/src/engine/types.d.ts +1 -0
- package/kotlin/sdk.tar.gz +0 -0
- package/package.json +1 -1
- package/src/android-bridge-dependencies.ts +93 -0
- package/src/android-bridge-packages.ts +1 -0
- package/src/android-gradle-sources.ts +76 -9
- package/src/androidGradleContract.ts +8 -0
- package/src/expo-kotlin-host.ts +20 -7
- package/src/expoKotlinContract.ts +1 -1
- package/src/java-module-abi.ts +7 -1
- package/src/kotlin-app.ts +120 -63
- package/src/kotlin-host.ts +1 -0
- package/src/kotlinSdkContract.ts +8 -1
package/src/kotlin-app.ts
CHANGED
|
@@ -19,6 +19,7 @@ import frameworkThemes from './generated/android-framework-themes.json' with { t
|
|
|
19
19
|
import { isRecord } from './is-record'
|
|
20
20
|
import { composeBomVersions } from './kotlin-compose-bom'
|
|
21
21
|
import { KotlinVersionCatalog } from './kotlin-version-catalog'
|
|
22
|
+
import type { AndroidGradleDependency } from './androidGradleContract'
|
|
22
23
|
|
|
23
24
|
// statusBarColor and navigationBarColor are ARGB
|
|
24
25
|
export interface KotlinWindowTheme {
|
|
@@ -35,6 +36,7 @@ export interface KotlinAppProject {
|
|
|
35
36
|
projectDir: string
|
|
36
37
|
moduleDir: string
|
|
37
38
|
sources: string[]
|
|
39
|
+
javaSources: string[]
|
|
38
40
|
language: string
|
|
39
41
|
usesSerialization: boolean
|
|
40
42
|
packageName: string
|
|
@@ -93,6 +95,7 @@ const PLUGINS = new Set([
|
|
|
93
95
|
// match their Android pins (Peach's activity actuals are that version's); the
|
|
94
96
|
// lifecycle and savedstate artifacts are Peach's platform actuals.
|
|
95
97
|
const PLATFORM_GROUPS = new Set(['androidx.lifecycle', 'androidx.savedstate'])
|
|
98
|
+
const PLATFORM_ARTIFACTS = new Set(['androidx.databinding:viewbinding'])
|
|
96
99
|
// pinned by group, or by group and artifact where a group's artifacts version
|
|
97
100
|
// apart (material-icons-core stopped at 1.7, beside material-ripple)
|
|
98
101
|
const ANDROID_PIN: Record<string, keyof AndroidPins> = {
|
|
@@ -104,10 +107,12 @@ const ANDROID_PIN: Record<string, keyof AndroidPins> = {
|
|
|
104
107
|
'androidx.navigation': 'navigation',
|
|
105
108
|
'androidx.activity': 'activity',
|
|
106
109
|
'org.jetbrains.kotlinx:kotlinx-serialization-core': 'serializationCore',
|
|
110
|
+
'org.jetbrains.kotlinx:kotlinx-serialization-core-jvm': 'serializationCore',
|
|
107
111
|
'org.jetbrains.kotlin:kotlin-stdlib': 'kotlin',
|
|
108
112
|
'org.jetbrains.kotlin:kotlin-stdlib-jdk7': 'kotlin',
|
|
109
113
|
'org.jetbrains.kotlin:kotlin-stdlib-jdk8': 'kotlin',
|
|
110
114
|
'org.jetbrains.kotlinx:kotlinx-coroutines-core': 'coroutines',
|
|
115
|
+
'org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm': 'coroutines',
|
|
111
116
|
'org.jetbrains.kotlinx:kotlinx-coroutines-android': 'coroutines',
|
|
112
117
|
}
|
|
113
118
|
|
|
@@ -242,6 +247,7 @@ async function checkModuleGradle(
|
|
|
242
247
|
gradle: { file: string; text: string },
|
|
243
248
|
pins: AndroidPins,
|
|
244
249
|
catalog: KotlinVersionCatalog,
|
|
250
|
+
nativeDependencies: readonly AndroidGradleDependency[] | null,
|
|
245
251
|
) {
|
|
246
252
|
const at = (index: number) => `${gradle.file}:${lineOf(gradle.text, index)}`
|
|
247
253
|
const coordinates = (value: string, where: string): string[] => {
|
|
@@ -260,7 +266,13 @@ async function checkModuleGradle(
|
|
|
260
266
|
const plugin = match[3]
|
|
261
267
|
? catalog.plugin(match[3], at(match.index)).id
|
|
262
268
|
: (match[1] ?? `org.jetbrains.kotlin.${match[2]}`)
|
|
263
|
-
if (
|
|
269
|
+
if (
|
|
270
|
+
!PLUGINS.has(plugin) &&
|
|
271
|
+
!(
|
|
272
|
+
nativeDependencies !== null &&
|
|
273
|
+
(plugin === 'com.google.devtools.ksp' || plugin === 'io.gitlab.arturbosch.detekt')
|
|
274
|
+
)
|
|
275
|
+
)
|
|
264
276
|
throw new Error(`${at(match.index)}: plugin ${plugin} is not supported by Peach`)
|
|
265
277
|
if (
|
|
266
278
|
plugin === 'org.jetbrains.kotlin.plugin.serialization' &&
|
|
@@ -270,53 +282,66 @@ async function checkModuleGradle(
|
|
|
270
282
|
)
|
|
271
283
|
usesSerialization = true
|
|
272
284
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
285
|
+
if (nativeDependencies !== null) {
|
|
286
|
+
for (const dependency of nativeDependencies) {
|
|
287
|
+
if (dependency.kind !== 'module')
|
|
288
|
+
throw new Error(
|
|
289
|
+
`${gradle.file}: ${dependency.kind} dependency ${dependency.name} is not in Peach's Kotlin closure`,
|
|
290
|
+
)
|
|
291
|
+
dependencies.push({
|
|
292
|
+
coordinate: `${dependency.group}:${dependency.name}:${dependency.version}`,
|
|
293
|
+
where: gradle.file,
|
|
294
|
+
})
|
|
282
295
|
}
|
|
283
|
-
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
continue
|
|
296
|
+
} else
|
|
297
|
+
for (const block of gradle.text.matchAll(/\bdependencies\s*\{/g)) {
|
|
298
|
+
// the block runs to its matching brace, on one line or many; every
|
|
299
|
+
// statement in it must be a literal dependency Peach can check
|
|
300
|
+
const start = block.index + block[0].length
|
|
301
|
+
let depth = 1
|
|
302
|
+
let end = start
|
|
303
|
+
for (; end < gradle.text.length && depth > 0; end++) {
|
|
304
|
+
if (gradle.text[end] === '{') depth++
|
|
305
|
+
else if (gradle.text[end] === '}') depth--
|
|
294
306
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const
|
|
304
|
-
if (
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
307
|
+
if (depth > 0)
|
|
308
|
+
throw new Error(`${at(block.index)}: dependencies block never closes`)
|
|
309
|
+
const body = gradle.text.slice(start, end - 1)
|
|
310
|
+
const platformVariables = new Map<string, string>()
|
|
311
|
+
for (const statement of body.matchAll(/[^\n;]+/g)) {
|
|
312
|
+
const text = statement[0].replace(/\/\/.*$/, '').trim()
|
|
313
|
+
if (!text) continue
|
|
314
|
+
const where = at(start + statement.index)
|
|
315
|
+
const variable = /^val\s+(\w+)\s*=\s*(platform\(.*\))$/.exec(text)
|
|
316
|
+
if (variable?.[1] && variable[2]) {
|
|
317
|
+
platformVariables.set(variable[1], variable[2])
|
|
318
|
+
continue
|
|
319
|
+
}
|
|
320
|
+
const call = /^(\w+)\s*\(\s*(.*?)\s*\)$/.exec(text)
|
|
321
|
+
if (!call) throw new Error(`${where}: ${text} is not a literal dependency`)
|
|
322
|
+
const [, configuration = '', value = ''] = call
|
|
323
|
+
if (/^(test|androidTest|debug|release)/.test(configuration)) continue
|
|
324
|
+
const platform = /^platform\(\s*(.*?)\s*\)$/.exec(
|
|
325
|
+
platformVariables.get(value) ?? value,
|
|
326
|
+
)
|
|
327
|
+
if (platform?.[1]) {
|
|
328
|
+
const declared = coordinates(platform[1], where)
|
|
329
|
+
if (declared.length !== 1 || !declared[0])
|
|
330
|
+
throw new Error(`${where}: platform expects one BOM coordinate`)
|
|
331
|
+
for (const [name, version] of await composeBomVersions(declared[0])) {
|
|
332
|
+
const previous = platforms.get(name)
|
|
333
|
+
if (previous && previous !== version)
|
|
334
|
+
throw new Error(
|
|
335
|
+
`${where}: conflicting BOM versions ${previous} and ${version} for ${name}`,
|
|
336
|
+
)
|
|
337
|
+
platforms.set(name, version)
|
|
338
|
+
}
|
|
339
|
+
} else {
|
|
340
|
+
for (const coordinate of coordinates(value, where))
|
|
341
|
+
dependencies.push({ coordinate, where })
|
|
313
342
|
}
|
|
314
|
-
} else {
|
|
315
|
-
for (const coordinate of coordinates(value, where))
|
|
316
|
-
dependencies.push({ coordinate, where })
|
|
317
343
|
}
|
|
318
344
|
}
|
|
319
|
-
}
|
|
320
345
|
for (const { coordinate, where } of dependencies) {
|
|
321
346
|
const parts = /^([^:]+):([^:]+)(?::([^:]+))?$/.exec(coordinate)
|
|
322
347
|
if (!parts)
|
|
@@ -336,7 +361,7 @@ async function checkModuleGradle(
|
|
|
336
361
|
throw new Error(
|
|
337
362
|
`${where}: ${name}:${version} differs from Peach's ${pin} pin ${pins[pin]}`,
|
|
338
363
|
)
|
|
339
|
-
} else if (!PLATFORM_GROUPS.has(group))
|
|
364
|
+
} else if (!PLATFORM_GROUPS.has(group) && !PLATFORM_ARTIFACTS.has(name))
|
|
340
365
|
throw new Error(`${where}: ${name} is not in Peach's Kotlin closure`)
|
|
341
366
|
}
|
|
342
367
|
return { usesSerialization }
|
|
@@ -498,7 +523,7 @@ function isLauncher(element: XmlElement): boolean {
|
|
|
498
523
|
|
|
499
524
|
export async function readKotlinApp(
|
|
500
525
|
moduleArg: string,
|
|
501
|
-
options: { activity?: string; pins: AndroidPins },
|
|
526
|
+
options: { activity?: string; variant?: string; pins: AndroidPins },
|
|
502
527
|
): Promise<KotlinAppProject> {
|
|
503
528
|
const moduleDir = fs.realpathSync(path.resolve(moduleArg))
|
|
504
529
|
const manifestFile = path.join(moduleDir, 'src/main/AndroidManifest.xml')
|
|
@@ -520,12 +545,42 @@ export async function readKotlinApp(
|
|
|
520
545
|
const gradle = readGradle(moduleDir)
|
|
521
546
|
if (!gradle) throw new Error(`${moduleDir} has no build.gradle`)
|
|
522
547
|
const catalog = new KotlinVersionCatalog(projectDir)
|
|
523
|
-
const
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
548
|
+
const variant = options.variant
|
|
549
|
+
const selected =
|
|
550
|
+
variant === undefined
|
|
551
|
+
? null
|
|
552
|
+
: await (async () => {
|
|
553
|
+
const { resolveAndroidGradleSources } = await import('./android-gradle-sources')
|
|
554
|
+
const [model] = await resolveAndroidGradleSources({
|
|
555
|
+
root: projectDir,
|
|
556
|
+
projects: [moduleDir],
|
|
557
|
+
variant,
|
|
558
|
+
})
|
|
559
|
+
if (!model || model.applicationId === null || model.targetSdk === null)
|
|
560
|
+
throw new Error(
|
|
561
|
+
`${moduleDir}: ${options.variant} is not an Android application variant`,
|
|
562
|
+
)
|
|
563
|
+
return {
|
|
564
|
+
...model,
|
|
565
|
+
applicationId: model.applicationId,
|
|
566
|
+
targetSdk: model.targetSdk,
|
|
567
|
+
}
|
|
568
|
+
})()
|
|
569
|
+
const { usesSerialization } = await checkModuleGradle(
|
|
570
|
+
gradle,
|
|
571
|
+
options.pins,
|
|
572
|
+
catalog,
|
|
573
|
+
selected?.dependencies ?? null,
|
|
528
574
|
)
|
|
575
|
+
const namespace = selected
|
|
576
|
+
? selected.namespace
|
|
577
|
+
: gradleLiteral(gradle, 'namespace', '"[\\w.]+"', catalog)
|
|
578
|
+
const applicationId = selected
|
|
579
|
+
? selected.applicationId
|
|
580
|
+
: gradleLiteral(gradle, 'applicationId', '"[\\w.]+"', catalog)
|
|
581
|
+
const targetSdk = selected
|
|
582
|
+
? selected.targetSdk
|
|
583
|
+
: Number(gradleLiteral(gradle, 'targetSdk(?:Version)?', '\\d+', catalog))
|
|
529
584
|
if (!Number.isInteger(targetSdk) || targetSdk <= 0)
|
|
530
585
|
throw new Error(`${gradle.file}: declares no literal targetSdk`)
|
|
531
586
|
const kotlin = kotlinPluginVersion(projectDir, gradle, catalog)
|
|
@@ -658,21 +713,22 @@ export async function readKotlinApp(
|
|
|
658
713
|
if (!softInputAdjust)
|
|
659
714
|
throw new Error(`${manifestFile}: unknown windowSoftInputMode ${adjust}`)
|
|
660
715
|
|
|
661
|
-
const sources: string[] = []
|
|
662
|
-
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
716
|
+
const sources: string[] = selected ? selected.kotlin : []
|
|
717
|
+
if (!selected)
|
|
718
|
+
for (const set of ['java', 'kotlin']) {
|
|
719
|
+
const dir = path.join(moduleDir, 'src/main', set)
|
|
720
|
+
if (!fs.existsSync(dir)) continue
|
|
721
|
+
const walk = (current: string) => {
|
|
722
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
723
|
+
const full = path.join(current, entry.name)
|
|
724
|
+
if (entry.isDirectory()) walk(full)
|
|
725
|
+
else if (entry.name.endsWith('.java'))
|
|
726
|
+
throw new Error(`${full}: Java sources are not supported by peach open`)
|
|
727
|
+
else if (entry.name.endsWith('.kt')) sources.push(full)
|
|
728
|
+
}
|
|
672
729
|
}
|
|
730
|
+
walk(dir)
|
|
673
731
|
}
|
|
674
|
-
walk(dir)
|
|
675
|
-
}
|
|
676
732
|
if (sources.length === 0)
|
|
677
733
|
throw new Error(`${moduleDir}/src/main holds no Kotlin sources`)
|
|
678
734
|
const resources = {
|
|
@@ -683,6 +739,7 @@ export async function readKotlinApp(
|
|
|
683
739
|
projectDir,
|
|
684
740
|
moduleDir,
|
|
685
741
|
sources: sources.sort(),
|
|
742
|
+
javaSources: selected ? selected.java : [],
|
|
686
743
|
language,
|
|
687
744
|
usesSerialization,
|
|
688
745
|
packageName: applicationId ?? base,
|
package/src/kotlin-host.ts
CHANGED
package/src/kotlinSdkContract.ts
CHANGED
|
@@ -37,12 +37,19 @@ export const KOTLIN_SDK_PROFILES = {
|
|
|
37
37
|
'BridgeSources',
|
|
38
38
|
'AndroidViewSources',
|
|
39
39
|
'ComposeSources',
|
|
40
|
+
'AndroidComposeSources',
|
|
40
41
|
'ExpoComposeSources',
|
|
41
42
|
],
|
|
42
43
|
},
|
|
43
44
|
app: {
|
|
44
45
|
compose: true,
|
|
45
|
-
directories: [
|
|
46
|
+
directories: [
|
|
47
|
+
...platform,
|
|
48
|
+
'ComposeSources',
|
|
49
|
+
'AppSources',
|
|
50
|
+
'AndroidViewSources',
|
|
51
|
+
'AndroidComposeSources',
|
|
52
|
+
],
|
|
46
53
|
},
|
|
47
54
|
} satisfies Record<string, { compose: boolean; directories: string[] }>
|
|
48
55
|
|