@akanjs/devkit 3.0.0-beta.8 → 3.0.0
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/DEV_RUNTIME_KNOBS.md +44 -26
- package/README.ko.md +21 -7
- package/README.md +17 -8
- package/abstractDoc.test.ts +6 -15
- package/abstractDoc.ts +6 -8
- package/agentsIndex.test.ts +4 -7
- package/agentsIndex.ts +6 -22
- package/akanApp/BackendImportGraph.test.ts +8 -22
- package/akanApp/BackendImportGraph.ts +1 -20
- package/akanApp/akanApp.host.test.ts +56 -3
- package/akanApp/akanApp.host.ts +218 -278
- package/akanApp/devBootLatch.test.ts +39 -0
- package/akanApp/devBootLatch.ts +39 -0
- package/akanApp/devHostPolicy.test.ts +81 -35
- package/akanApp/devHostPolicy.ts +41 -102
- package/akanConfig/akanBin.test.ts +62 -0
- package/akanConfig/akanBin.ts +78 -0
- package/akanConfig/akanConfig.test.ts +439 -141
- package/akanConfig/akanConfig.ts +359 -275
- package/akanConfig/index.ts +1 -0
- package/akanConfig/types.ts +22 -8
- package/akanContext.ts +110 -160
- package/akanMcpContract.ts +28 -73
- package/appSelectionMemory.ts +1 -4
- package/applicationBuildReporter.ts +37 -5
- package/applicationBuildRunner.test.ts +41 -5
- package/applicationBuildRunner.ts +71 -63
- package/applicationTestPreload.ts +3 -12
- package/artifact/implicitRootLayout.test.ts +32 -30
- package/artifact/implicitRootLayout.ts +58 -106
- package/artifact/routeSeedIndex.test.ts +7 -6
- package/artifact/routeSeedIndex.ts +11 -44
- package/biome.base.json +35 -2
- package/biomeBase.ts +2 -5
- package/cloud/cloudApi.test.ts +202 -0
- package/cloud/cloudApi.ts +77 -39
- package/cloud/configLock.test.ts +64 -0
- package/cloud/configLock.ts +96 -0
- package/cloud/constants.ts +26 -5
- package/cloud/globalConfig.ts +71 -32
- package/codeAgent/agent/AkanCodeServices.ts +97 -0
- package/codeAgent/agent/AkanContextFiles.ts +94 -0
- package/codeAgent/agent/CodeAgent.ts +551 -0
- package/codeAgent/agent/CodeAgentAsks.ts +66 -0
- package/codeAgent/agent/CodeAgentEventMapper.ts +225 -0
- package/codeAgent/agent/CodeAgentGate.ts +93 -0
- package/codeAgent/agent/CodeAgentProxy.ts +82 -0
- package/codeAgent/agent/CodeAgentRpcHost.ts +103 -0
- package/codeAgent/agent/CodeAgentRpcListener.ts +109 -0
- package/codeAgent/agent/CodeAgentStreamPrinter.ts +86 -0
- package/codeAgent/agent/CodeAgentSuspended.ts +85 -0
- package/codeAgent/agent/CodeAgentUi.ts +47 -0
- package/codeAgent/agent/CodeMailbox.ts +148 -0
- package/codeAgent/agent/CodeSessionFork.ts +56 -0
- package/codeAgent/agent/CodeSessionIndex.ts +78 -0
- package/codeAgent/agent/SubagentPool.ts +214 -0
- package/codeAgent/agent/akanCodeModel.ts +47 -0
- package/codeAgent/agent/akanCodePaths.ts +31 -0
- package/codeAgent/agent/akanContextFiles.test.ts +114 -0
- package/codeAgent/agent/akanSystemPrompt.ts +46 -0
- package/codeAgent/agent/codeAgent.test.ts +178 -0
- package/codeAgent/agent/codeAgentContract.test.ts +523 -0
- package/codeAgent/agent/codeAgentProxy.test.ts +74 -0
- package/codeAgent/agent/codeAgentRpcListener.test.ts +113 -0
- package/codeAgent/agent/codeAgentSuspended.test.ts +47 -0
- package/codeAgent/agent/codeMailbox.test.ts +76 -0
- package/codeAgent/agent/codeSessionFork.test.ts +58 -0
- package/codeAgent/agent/codeSessionIndex.test.ts +77 -0
- package/codeAgent/agent/consoleToStderr.ts +8 -0
- package/codeAgent/agent/jsonLines.ts +29 -0
- package/codeAgent/agent/stringArg.ts +5 -0
- package/codeAgent/feedback/DevLogFeedback.ts +82 -0
- package/codeAgent/feedback/PreviewChrome.ts +82 -0
- package/codeAgent/feedback/PreviewFeedback.ts +46 -0
- package/codeAgent/feedback/PreviewView.ts +95 -0
- package/codeAgent/feedback/TurnFeedback.ts +98 -0
- package/codeAgent/feedback/VerifyFeedback.ts +40 -0
- package/codeAgent/feedback/previewChrome.test.ts +73 -0
- package/codeAgent/index.ts +34 -0
- package/codeAgent/skills/akan-code/SKILL.md +130 -0
- package/codeAgent/skills/akan-debug/SKILL.md +42 -0
- package/codeAgent/skills/akan-deps/SKILL.md +50 -0
- package/codeAgent/skills/akan-err/SKILL.md +39 -0
- package/codeAgent/skills/akan-module/SKILL.md +45 -0
- package/codeAgent/skills/akan-scaffold/SKILL.md +76 -0
- package/codeAgent/skills/akan-scalar/SKILL.md +52 -0
- package/codeAgent/skills/akan-service/SKILL.md +34 -0
- package/codeAgent/skills/akan-store/SKILL.md +67 -0
- package/codeAgent/skills/akan-ui/SKILL.md +63 -0
- package/codeAgent/skills/akan-validate/SKILL.md +44 -0
- package/codeAgent/tools/AkanCli.ts +50 -0
- package/codeAgent/tools/AkanCodePlugins.ts +136 -0
- package/codeAgent/tools/AkanEditScope.ts +48 -0
- package/codeAgent/tools/AkanEnvKeys.ts +50 -0
- package/codeAgent/tools/AkanToolPack.ts +92 -0
- package/codeAgent/tools/AkanVerifier.ts +48 -0
- package/codeAgent/tools/AskToolPack.ts +99 -0
- package/codeAgent/tools/MailToolPack.ts +76 -0
- package/codeAgent/tools/McpClient.ts +187 -0
- package/codeAgent/tools/McpOAuth.ts +233 -0
- package/codeAgent/tools/McpOAuthLoopback.ts +64 -0
- package/codeAgent/tools/McpServerConfig.ts +129 -0
- package/codeAgent/tools/McpSignIn.ts +158 -0
- package/codeAgent/tools/McpTokenStore.ts +81 -0
- package/codeAgent/tools/McpToolPack.ts +199 -0
- package/codeAgent/tools/SessionToolPack.ts +91 -0
- package/codeAgent/tools/WebToolPack.ts +147 -0
- package/codeAgent/tools/akanCodePlugins.test.ts +677 -0
- package/codeAgent/tools/askToolPack.test.ts +116 -0
- package/codeAgent/tools/mcpOAuth.test.ts +612 -0
- package/codeAgent/tools/mcpServerConfig.test.ts +212 -0
- package/codegenLock.test.ts +4 -13
- package/codegenLock.ts +3 -17
- package/commandDecorators/argMeta.ts +1 -5
- package/commandDecorators/camelToKebabCase.ts +1 -0
- package/commandDecorators/command.ts +46 -102
- package/commandDecorators/commandBuilder.ts +30 -61
- package/commandDecorators/commandDecorators.test.ts +2 -10
- package/commandDecorators/dependencyBuilder.ts +10 -1
- package/commandDecorators/helpFormatter.ts +68 -145
- package/commandDecorators/index.ts +0 -2
- package/commandDecorators/targetMeta.ts +9 -7
- package/createTunnel.ts +7 -14
- package/csrE2e/csrE2eHarness.fixture.ts +505 -0
- package/csrE2e/csrFastRefresh.e2e.test.ts +233 -0
- package/csrE2e/csrPageStack.e2e.test.ts +252 -0
- package/csrE2e/csrPatchFirst.e2e.test.ts +87 -0
- package/csrE2e/csrRootLayout.e2e.test.ts +134 -0
- package/csrE2e/devHmrLatency.e2e.test.ts +391 -0
- package/csrE2e/registryVendor.e2e.test.ts +221 -0
- package/csrE2e/ssrRegistry.e2e.test.ts +644 -0
- package/dependencyScanner.test.ts +4 -16
- package/dependencyScanner.ts +31 -80
- package/devkitUtils.test.ts +48 -20
- package/executors.linkFallback.test.ts +103 -0
- package/executors.test.ts +176 -106
- package/executors.ts +212 -498
- package/fileEditor.ts +9 -37
- package/{getDirname.test.ts → fileSys.test.ts} +5 -3
- package/fileSys.ts +22 -9
- package/formSetterScanner.ts +3 -16
- package/frontendBuild/allRoutesBuilder.ts +7 -21
- package/frontendBuild/autoImportSync.test.ts +27 -38
- package/frontendBuild/autoImportSync.ts +31 -65
- package/frontendBuild/buildRouteClient.test.ts +123 -37
- package/frontendBuild/bundleDefine.test.ts +12 -0
- package/frontendBuild/bundleDefine.ts +16 -0
- package/frontendBuild/clientBuildTypes.ts +5 -36
- package/frontendBuild/clientEntriesBundler.ts +9 -40
- package/frontendBuild/clientEntryDiscovery.test.ts +112 -0
- package/frontendBuild/clientEntryDiscovery.ts +122 -110
- package/frontendBuild/csrArtifactBuilder.ts +9 -31
- package/frontendBuild/csrDevArtifactWriter.test.ts +151 -0
- package/frontendBuild/csrDevArtifactWriter.ts +307 -0
- package/frontendBuild/csrDevBundler.test.ts +66 -0
- package/frontendBuild/csrDevBundler.ts +95 -0
- package/frontendBuild/csrDevFactoryCheck.test.ts +33 -0
- package/frontendBuild/csrDevFactoryCheck.ts +39 -0
- package/frontendBuild/csrDevModuleCompiler.test.ts +293 -0
- package/frontendBuild/csrDevModuleCompiler.ts +422 -0
- package/frontendBuild/csrDevPatcher.test.ts +572 -0
- package/frontendBuild/csrDevPatcher.ts +548 -0
- package/frontendBuild/csrDevPaths.ts +145 -0
- package/frontendBuild/csrDevResolver.test.ts +239 -0
- package/frontendBuild/csrDevResolver.ts +363 -0
- package/frontendBuild/csrDevTypes.ts +61 -0
- package/frontendBuild/csrEntryFiles.ts +24 -0
- package/frontendBuild/cssCandidateCache.test.ts +0 -6
- package/frontendBuild/cssCandidateCache.ts +6 -41
- package/frontendBuild/cssCompiler.ts +31 -82
- package/frontendBuild/cssImportResolver.ts +6 -19
- package/frontendBuild/devChangePlanner.ts +7 -10
- package/frontendBuild/devGeneratedIndexSync.test.ts +12 -27
- package/frontendBuild/devGeneratedIndexSync.ts +1 -4
- package/frontendBuild/devRegistryBundler.ts +192 -0
- package/frontendBuild/fontOptimizer.test.ts +6 -14
- package/frontendBuild/fontOptimizer.ts +15 -72
- package/frontendBuild/fontPruner.test.ts +5 -10
- package/frontendBuild/fontPruner.ts +5 -20
- package/frontendBuild/frontendBuild.test.ts +57 -70
- package/frontendBuild/hmrChangeClassifier.ts +2 -2
- package/frontendBuild/hmrWatcher.test.ts +59 -32
- package/frontendBuild/hmrWatcher.ts +31 -74
- package/frontendBuild/index.ts +4 -0
- package/frontendBuild/pagesBundleBuilder.ts +28 -30
- package/frontendBuild/pagesEntrySourceGenerator.ts +56 -6
- package/frontendBuild/precompressArtifacts.ts +5 -18
- package/frontendBuild/registryMetadataFingerprint.test.ts +63 -0
- package/frontendBuild/registryMetadataFingerprint.ts +28 -0
- package/frontendBuild/routeClientBuilder.ts +100 -62
- package/frontendBuild/routesManifestArtifactSerializer.ts +5 -36
- package/frontendBuild/serverGraphFile.test.ts +77 -0
- package/frontendBuild/serverGraphFile.ts +93 -0
- package/frontendBuild/sourceMtimeIndex.test.ts +41 -97
- package/frontendBuild/sourceMtimeIndex.ts +19 -130
- package/frontendBuild/ssrBaseArtifactBuilder.ts +19 -13
- package/frontendBuild/ssrDevBundler.ts +85 -0
- package/frontendBuild/styleContract.ts +1 -8
- package/frontendBuild/themeValidator.ts +4 -26
- package/frontendBuild/watchRootResolver.test.ts +23 -42
- package/frontendBuild/watchRootResolver.ts +5 -27
- package/getRelatedCnsts.ts +12 -92
- package/incrementalBuilder/buildBatch.proc.ts +147 -63
- package/incrementalBuilder/buildBatchProtocol.ts +13 -38
- package/incrementalBuilder/buildBatchRunner.test.ts +65 -0
- package/incrementalBuilder/buildBatchRunner.ts +26 -38
- package/incrementalBuilder/builderChannel.test.ts +24 -49
- package/incrementalBuilder/builderChannel.ts +6 -37
- package/incrementalBuilder/builderRequestRouter.test.ts +0 -8
- package/incrementalBuilder/builderRequestRouter.ts +5 -24
- package/incrementalBuilder/builderWorkQueue.test.ts +94 -0
- package/incrementalBuilder/builderWorkQueue.ts +126 -0
- package/incrementalBuilder/devWatchBatch.test.ts +21 -24
- package/incrementalBuilder/incrementalBuilder.host.test.ts +53 -56
- package/incrementalBuilder/incrementalBuilder.host.ts +68 -81
- package/incrementalBuilder/incrementalBuilder.proc.test.ts +270 -0
- package/incrementalBuilder/incrementalBuilder.proc.ts +596 -208
- package/index.ts +5 -19
- package/integration/devResourceProbe.ts +50 -56
- package/integration/devStability.integration.test.ts +105 -199
- package/integration/devStabilityHarness.test.ts +13 -28
- package/integration/devStabilityHarness.ts +65 -330
- package/integration/ssrMemoryProbe.ts +41 -167
- package/libSource.test.ts +4 -15
- package/libSource.ts +19 -31
- package/lint/__fixtures__/no-document-cookie/bad.tsx +4 -0
- package/lint/__fixtures__/no-document-cookie/good.tsx +7 -0
- package/lint/__fixtures__/no-web-only-api-outside-webkit/bad.tsx +7 -0
- package/lint/__fixtures__/no-web-only-api-outside-webkit/good.tsx +11 -0
- package/lint/__fixtures__/no-web-storage/bad.tsx +6 -0
- package/lint/__fixtures__/no-web-storage/good.tsx +7 -0
- package/lint/gritRules.test.ts +8 -24
- package/lint/no-deep-internal-import.grit +2 -2
- package/lint/no-document-cookie.grit +29 -0
- package/lint/no-redeclare-predefined-endpoint.grit +2 -1
- package/lint/no-web-only-api-outside-webkit.grit +44 -0
- package/lint/no-web-storage.grit +30 -0
- package/linter.test.ts +1 -2
- package/linter.ts +26 -116
- package/mobile/desktopBin.test.ts +182 -0
- package/mobile/desktopBin.ts +144 -0
- package/mobile/desktopServerStage.test.ts +252 -0
- package/mobile/desktopServerStage.ts +178 -0
- package/mobile/index.ts +9 -0
- package/mobile/mobileTarget.test.ts +57 -8
- package/mobile/mobileTarget.ts +45 -26
- package/mobile/nativeApi.test.ts +30 -0
- package/mobile/nativeApi.ts +40 -0
- package/mobile/nativeApp.test.ts +184 -0
- package/mobile/nativeApp.ts +454 -0
- package/mobile/nativeAppLine.test.ts +69 -0
- package/mobile/nativeAppLine.ts +71 -0
- package/mobile/nativeConfig.test.ts +438 -0
- package/mobile/nativeConfig.ts +294 -0
- package/mobile/nativePluginFolders.test.ts +81 -0
- package/mobile/nativePluginFolders.ts +60 -0
- package/mobile/nativeWebDir.test.ts +80 -0
- package/mobile/nativeWebDir.ts +66 -0
- package/mobile/placeholderAppId.test.ts +13 -0
- package/mobile/placeholderAppId.ts +16 -0
- package/mobile/usageDescriptions.test.ts +27 -0
- package/mobile/usageDescriptions.ts +24 -0
- package/package.json +11 -11
- package/packageExports.test.ts +3 -18
- package/packageExportsMap.ts +3 -19
- package/piDependencyPins.test.ts +46 -0
- package/platformTest/BunTestReport.test.ts +60 -0
- package/platformTest/BunTestReport.ts +65 -0
- package/platformTest/IdleWatchedProcess.test.ts +56 -0
- package/platformTest/IdleWatchedProcess.ts +73 -0
- package/platformTest/LinuxDockerTarget.ts +105 -0
- package/platformTest/PlatformTestRun.test.ts +64 -0
- package/platformTest/PlatformTestRun.ts +141 -0
- package/platformTest/PlatformTestTarget.ts +142 -0
- package/platformTest/TestSnapshot.test.ts +72 -0
- package/platformTest/TestSnapshot.ts +103 -0
- package/platformTest/WindowsSshTarget.ts +151 -0
- package/prompter.ts +3 -13
- package/qualityScanner.test.ts +9 -26
- package/qualityScanner.ts +200 -286
- package/recipeScanner.test.ts +7 -12
- package/recipeScanner.ts +9 -38
- package/repoIdentity.ts +2 -9
- package/routeSourceValidator.test.ts +0 -1
- package/routeSourceValidator.ts +7 -42
- package/scanInfo.ts +91 -225
- package/selectModel.ts +1 -2
- package/semver.ts +3 -5
- package/slicePlanner.test.ts +6 -24
- package/slicePlanner.ts +11 -32
- package/spinner.test.ts +3 -8
- package/spinner.ts +4 -16
- package/sshTunnel.ts +1 -6
- package/ssrScanner.test.ts +1 -6
- package/ssrScanner.ts +103 -113
- package/stripAnsi.ts +3 -0
- package/subspace.test.ts +9 -25
- package/subspace.ts +48 -115
- package/subspaceConfig.ts +3 -11
- package/testHelpers.ts +194 -0
- package/transforms/asyncDefaultExportDetector.ts +3 -11
- package/transforms/barrelAnalyzer.ts +43 -135
- package/transforms/barrelImportsPlugin.ts +38 -175
- package/transforms/externalizeFrameworkPlugin.test.ts +39 -118
- package/transforms/externalizeFrameworkPlugin.ts +13 -87
- package/transforms/moduleSyntax.ts +32 -0
- package/transforms/rscUseClientTransform.ts +42 -20
- package/transforms/serverEnvPlugin.test.ts +103 -0
- package/transforms/serverEnvPlugin.ts +41 -0
- package/transforms/transforms.test.ts +166 -44
- package/transforms/tsconfigPackageResolver.test.ts +6 -24
- package/transforms/useClientBundlePlugin.ts +6 -23
- package/typeChecker.ts +7 -63
- package/types.ts +2 -0
- package/uploadRelease.ts +10 -25
- package/workflow/artifacts.ts +18 -0
- package/workflow/executor.test.ts +1 -12
- package/workflow/executor.ts +101 -110
- package/workflow/index.ts +0 -1
- package/workflow/moduleIndex.test.ts +4 -15
- package/workflow/moduleIndex.ts +9 -49
- package/workflow/plan.ts +18 -25
- package/workflow/render.ts +80 -96
- package/workflow/rolloutGate.test.ts +1 -1
- package/workflow/source.ts +52 -69
- package/workflow/sourceAst.ts +50 -0
- package/workspaceLayout.test.ts +18 -3
- package/workspaceLayout.ts +22 -23
- package/abstractCompactor.ts +0 -112
- package/aiEditor.test.ts +0 -60
- package/aiEditor.ts +0 -387
- package/applicationReleasePackager.ts +0 -209
- package/capacitorApp.test.ts +0 -372
- package/capacitorApp.ts +0 -1648
- package/commandDecorators/commandMeta.ts +0 -7
- package/commandDecorators/types.ts +0 -10
- package/getDirname.ts +0 -4
- package/guideline.ts +0 -19
- package/local/optimize-resource/ipcprobe/child.ts +0 -1
- package/local/optimize-resource/ipcprobe/parent.ts +0 -11
- package/workflow/primitive.ts +0 -59
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { cp, mkdir, rm } from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import type { App } from "./commandDecorators";
|
|
4
|
-
import { FileSys } from "./fileSys";
|
|
5
|
-
import { uploadRelease } from "./uploadRelease";
|
|
6
|
-
|
|
7
|
-
export interface ReleaseSourceOptions {
|
|
8
|
-
rebuild?: boolean;
|
|
9
|
-
buildNum?: number;
|
|
10
|
-
environment?: string;
|
|
11
|
-
local?: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface ApplicationReleasePackagerOptions {
|
|
15
|
-
build: () => Promise<void>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class ApplicationReleasePackager {
|
|
19
|
-
#app: App;
|
|
20
|
-
#build: () => Promise<void>;
|
|
21
|
-
|
|
22
|
-
constructor(app: App, options: ApplicationReleasePackagerOptions) {
|
|
23
|
-
this.#app = app;
|
|
24
|
-
this.#build = options.build;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async releaseSource({
|
|
28
|
-
rebuild,
|
|
29
|
-
buildNum = 0,
|
|
30
|
-
environment = "debug",
|
|
31
|
-
local = true,
|
|
32
|
-
}: ReleaseSourceOptions = {}): Promise<void> {
|
|
33
|
-
const { platformVersion } = await this.#prepareReleaseBuild({ rebuild, buildNum });
|
|
34
|
-
await this.#writeSourceArchive({ readme: this.#confidentialReadme() });
|
|
35
|
-
await uploadRelease(this.#app.name, {
|
|
36
|
-
local,
|
|
37
|
-
buildNum,
|
|
38
|
-
environment,
|
|
39
|
-
platformVersion,
|
|
40
|
-
workspaceRoot: this.#app.workspace.cwdPath,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async compressProjectFiles({ rebuild, buildNum = 0 }: ReleaseSourceOptions = {}): Promise<void> {
|
|
45
|
-
await this.#prepareReleaseBuild({ rebuild, buildNum });
|
|
46
|
-
await this.#writeSourceArchive({ readme: this.#publicReadme() });
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async #prepareReleaseBuild({ rebuild, buildNum }: { rebuild?: boolean; buildNum: number }) {
|
|
50
|
-
const akanConfig = await this.#app.getConfig();
|
|
51
|
-
const platformVersion = akanConfig.mobile.version;
|
|
52
|
-
const buildRoot = `${this.#app.workspace.workspaceRoot}/releases/builds/${this.#app.name}`;
|
|
53
|
-
if (await FileSys.dirExists(buildRoot)) await rm(buildRoot, { recursive: true, force: true });
|
|
54
|
-
await mkdir(buildRoot, { recursive: true });
|
|
55
|
-
if (rebuild || !(await FileSys.dirExists(`${this.#app.dist.cwdPath}/backend`))) await this.#build();
|
|
56
|
-
|
|
57
|
-
const buildVersion = `${platformVersion}-${buildNum}`;
|
|
58
|
-
const buildPath = `${buildRoot}/${buildVersion}`;
|
|
59
|
-
await mkdir(buildPath, { recursive: true });
|
|
60
|
-
await cp(`${this.#app.dist.cwdPath}/backend`, `${buildPath}/backend`, { recursive: true });
|
|
61
|
-
|
|
62
|
-
await cp(this.#app.dist.cwdPath, buildRoot, { recursive: true });
|
|
63
|
-
await rm(`${buildRoot}/frontend/.next`, { recursive: true, force: true });
|
|
64
|
-
|
|
65
|
-
const releaseRoot = this.#app.workspace.workspaceRoot;
|
|
66
|
-
// Pass a path relative to cwd so tar never sees a Windows drive letter (e.g. "C:\...")
|
|
67
|
-
// which GNU tar would interpret as a remote "host:file" spec.
|
|
68
|
-
const releaseArchivePath = path
|
|
69
|
-
.relative(releaseRoot, `${releaseRoot}/releases/builds/${this.#app.name}-release.tar.gz`)
|
|
70
|
-
.split(path.sep)
|
|
71
|
-
.join("/");
|
|
72
|
-
await this.#app.workspace.spawn("tar", ["-zcf", releaseArchivePath, "-C", buildRoot, "./"], { cwd: releaseRoot });
|
|
73
|
-
await this.#writeCsrZipIfPresent();
|
|
74
|
-
return { platformVersion };
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async #writeCsrZipIfPresent(): Promise<void> {
|
|
78
|
-
if (!(await FileSys.dirExists(`${this.#app.dist.cwdPath}/csr`))) return;
|
|
79
|
-
await cp(`${this.#app.dist.cwdPath}/csr`, "./csr", { recursive: true });
|
|
80
|
-
await this.#app.workspace.spawn("zip", [
|
|
81
|
-
"-r",
|
|
82
|
-
`${this.#app.workspace.workspaceRoot}/releases/builds/${this.#app.name}-appBuild.zip`,
|
|
83
|
-
"./csr",
|
|
84
|
-
]);
|
|
85
|
-
await rm("./csr", { recursive: true, force: true });
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
async #writeSourceArchive({ readme }: { readme: string }): Promise<void> {
|
|
89
|
-
const sourceRoot = `${this.#app.workspace.workspaceRoot}/releases/sources/${this.#app.name}`;
|
|
90
|
-
await this.#resetSourceRoot(sourceRoot);
|
|
91
|
-
await cp(this.#app.dist.cwdPath, `${sourceRoot}/apps/${this.#app.name}`, { recursive: true });
|
|
92
|
-
|
|
93
|
-
const libDeps = ["social", "shared", "platform", "util"];
|
|
94
|
-
await Promise.all(
|
|
95
|
-
libDeps.map((lib) =>
|
|
96
|
-
cp(`${this.#app.workspace.cwdPath}/libs/${lib}`, `${sourceRoot}/libs/${lib}`, { recursive: true }),
|
|
97
|
-
),
|
|
98
|
-
);
|
|
99
|
-
await Promise.all(
|
|
100
|
-
[".next", "ios", "android", "public/libs"].map(async (path) => {
|
|
101
|
-
const targetPath = `${sourceRoot}/apps/${this.#app.name}/${path}`;
|
|
102
|
-
if (await FileSys.dirExists(targetPath)) await rm(targetPath, { recursive: true, force: true });
|
|
103
|
-
}),
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
const syncPaths = [".husky", ".gitignore", "package.json"];
|
|
107
|
-
await Promise.all(
|
|
108
|
-
syncPaths.map((path) =>
|
|
109
|
-
cp(`${this.#app.workspace.cwdPath}/${path}`, `${sourceRoot}/${path}`, { recursive: true }),
|
|
110
|
-
),
|
|
111
|
-
);
|
|
112
|
-
await this.#writeSourceTsconfig(sourceRoot, libDeps);
|
|
113
|
-
await Bun.write(`${sourceRoot}/README.md`, readme);
|
|
114
|
-
const sourceCwd = this.#app.workspace.cwdPath;
|
|
115
|
-
// Pass a path relative to cwd so tar never sees a Windows drive letter (e.g. "C:\...")
|
|
116
|
-
// which GNU tar would interpret as a remote "host:file" spec.
|
|
117
|
-
const sourceArchivePath = path
|
|
118
|
-
.relative(sourceCwd, `${sourceCwd}/releases/sources/${this.#app.name}-source.tar.gz`)
|
|
119
|
-
.split(path.sep)
|
|
120
|
-
.join("/");
|
|
121
|
-
await this.#app.workspace.spawn("tar", ["-zcf", sourceArchivePath, "-C", sourceRoot, "./"], { cwd: sourceCwd });
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async #resetSourceRoot(sourceRoot: string): Promise<void> {
|
|
125
|
-
if (await FileSys.dirExists(sourceRoot)) {
|
|
126
|
-
const maxRetry = 3;
|
|
127
|
-
for (let i = 0; i < maxRetry; i++) {
|
|
128
|
-
try {
|
|
129
|
-
await rm(sourceRoot, { recursive: true, force: true });
|
|
130
|
-
} catch {
|
|
131
|
-
//
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
await mkdir(sourceRoot, { recursive: true });
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
async #writeSourceTsconfig(sourceRoot: string, libDeps: string[]): Promise<void> {
|
|
139
|
-
const tsconfig = (await this.#app.workspace.readJson("tsconfig.json")) as {
|
|
140
|
-
compilerOptions: { paths: Record<string, string[]> };
|
|
141
|
-
};
|
|
142
|
-
const pathEntries: [string, string[]][] = [[`@${this.#app.name}/*`, [`apps/${this.#app.name}/*`]]];
|
|
143
|
-
for (const lib of libDeps) {
|
|
144
|
-
pathEntries.push([`@${lib}`, [`libs/${lib}/index.ts`]], [`@${lib}/*`, [`libs/${lib}/*`]]);
|
|
145
|
-
}
|
|
146
|
-
tsconfig.compilerOptions.paths = Object.fromEntries(pathEntries) as Record<string, string[]>;
|
|
147
|
-
await Bun.write(`${sourceRoot}/tsconfig.json`, JSON.stringify(tsconfig, null, 2));
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
#confidentialReadme(): string {
|
|
151
|
-
return `# ${this.#app.name}
|
|
152
|
-
본 프로젝트의 소스코드 및 관련자료는 모두 비밀정보로 관리됩니다.
|
|
153
|
-
|
|
154
|
-
## Get Started
|
|
155
|
-
Run the code below.
|
|
156
|
-
\`\`\`
|
|
157
|
-
bun install -g bun
|
|
158
|
-
bun i
|
|
159
|
-
|
|
160
|
-
cat <<EOF >> .env
|
|
161
|
-
# ENV For Server => debug | debug.local | develop | develop.local | main | main.local
|
|
162
|
-
SERVER_ENV=debug.local
|
|
163
|
-
# Run Mode For Server => federation | batch | all
|
|
164
|
-
SERVER_MODE=federation
|
|
165
|
-
# ENV For Client => debug | debug.local | develop | develop.local | main | main.local
|
|
166
|
-
AKAN_PUBLIC_CLIENT_ENV=debug.local
|
|
167
|
-
ANALYZE=false
|
|
168
|
-
EOF
|
|
169
|
-
|
|
170
|
-
akn start-backend ${this.#app.name}
|
|
171
|
-
# or akn start-frontend ${this.#app.name}, etc
|
|
172
|
-
\`\`\`
|
|
173
|
-
|
|
174
|
-
## Build
|
|
175
|
-
Run the code below.
|
|
176
|
-
\`\`\`
|
|
177
|
-
akn build-backend ${this.#app.name}
|
|
178
|
-
# or akn build-frontend ${this.#app.name}, etc
|
|
179
|
-
\`\`\`
|
|
180
|
-
`;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
#publicReadme(): string {
|
|
184
|
-
return `# ${this.#app.name}
|
|
185
|
-
## Get Started
|
|
186
|
-
Run the code below.
|
|
187
|
-
\`\`\`
|
|
188
|
-
cat <<EOF >> .env
|
|
189
|
-
# ENV For Server => debug | debug.local | develop | develop.local | main | main.local
|
|
190
|
-
SERVER_ENV=debug.local
|
|
191
|
-
# Run Mode For Server => federation | batch | all
|
|
192
|
-
SERVER_MODE=federation
|
|
193
|
-
# ENV For Client => debug | debug.local | develop | develop.local | main | main.local
|
|
194
|
-
AKAN_PUBLIC_CLIENT_ENV=debug.local
|
|
195
|
-
ANALYZE=false
|
|
196
|
-
EOF
|
|
197
|
-
|
|
198
|
-
akan start ${this.#app.name}
|
|
199
|
-
\`\`\`
|
|
200
|
-
|
|
201
|
-
## Build
|
|
202
|
-
Run the code below.
|
|
203
|
-
\`\`\`
|
|
204
|
-
akan build ${this.#app.name}
|
|
205
|
-
# or akn build-frontend ${this.#app.name}, etc
|
|
206
|
-
\`\`\`
|
|
207
|
-
`;
|
|
208
|
-
}
|
|
209
|
-
}
|
package/capacitorApp.test.ts
DELETED
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, test } from "bun:test";
|
|
2
|
-
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
-
import os from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import type { AkanMobileTargetConfig } from "./akanConfig";
|
|
6
|
-
import {
|
|
7
|
-
ANDROID_MIN_SDK_VERSION,
|
|
8
|
-
assertJsonSerializable,
|
|
9
|
-
buildIosNativeRunCommand,
|
|
10
|
-
classifyIosRunFailure,
|
|
11
|
-
clearRootCapacitorConfigs,
|
|
12
|
-
formatAndroidReleaseSigningError,
|
|
13
|
-
getAdbDeviceStateIssues,
|
|
14
|
-
getAndroidLocalServerHost,
|
|
15
|
-
getMissingAndroidReleaseSigningKeys,
|
|
16
|
-
isPlaceholderAppId,
|
|
17
|
-
materializeCapacitorConfig,
|
|
18
|
-
parseDevicectlDevices,
|
|
19
|
-
parseIosRuntimeMajor,
|
|
20
|
-
parseSimctlDevices,
|
|
21
|
-
raiseGradleMinSdkVersion,
|
|
22
|
-
rootCapacitorConfigFilenames,
|
|
23
|
-
SWIFTUICORE_MIN_IOS_MAJOR,
|
|
24
|
-
sanitizeIosNativeRunEnv,
|
|
25
|
-
selectLocalDevHost,
|
|
26
|
-
sortIosRunTargets,
|
|
27
|
-
writeRootCapacitorConfig,
|
|
28
|
-
} from "./capacitorApp";
|
|
29
|
-
|
|
30
|
-
const tempRoots: string[] = [];
|
|
31
|
-
|
|
32
|
-
const makeTempRoot = async () => {
|
|
33
|
-
const root = await mkdtemp(path.join(os.tmpdir(), "akan-capacitor-app-"));
|
|
34
|
-
tempRoots.push(root);
|
|
35
|
-
return root;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const baseTarget: AkanMobileTargetConfig = {
|
|
39
|
-
name: "default",
|
|
40
|
-
appName: "Minimal",
|
|
41
|
-
appId: "com.minimal.app",
|
|
42
|
-
version: "1.2.3",
|
|
43
|
-
buildNum: 7,
|
|
44
|
-
basePath: "admin",
|
|
45
|
-
indexPath: "/dashboard",
|
|
46
|
-
assets: { icon: "mobile/icon.png" },
|
|
47
|
-
permissions: ["camera"],
|
|
48
|
-
deepLinks: { schemes: ["minimal"], domains: ["minimal.app"] },
|
|
49
|
-
files: { android: { "app/google-services.json": "private/google-services.json" } },
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
afterEach(async () => {
|
|
53
|
-
await Promise.all(tempRoots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe("materializeCapacitorConfig", () => {
|
|
57
|
-
test("writes only Capacitor fields for release config", () => {
|
|
58
|
-
const config = materializeCapacitorConfig(
|
|
59
|
-
{
|
|
60
|
-
...baseTarget,
|
|
61
|
-
plugins: { CapacitorHttp: { enabled: true } },
|
|
62
|
-
android: { flavor: "qa" },
|
|
63
|
-
ios: { scheme: "App QA" },
|
|
64
|
-
cordova: { preferences: { ScrollEnabled: "false" } },
|
|
65
|
-
experimental: { ios: { spm: { swiftToolsVersion: "5.9" } } },
|
|
66
|
-
},
|
|
67
|
-
{ operation: "release" },
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
expect(config).toMatchObject({
|
|
71
|
-
appId: "com.minimal.app",
|
|
72
|
-
appName: "Minimal",
|
|
73
|
-
webDir: ".akan/mobile/default/www",
|
|
74
|
-
plugins: {
|
|
75
|
-
CapacitorCookies: { enabled: true },
|
|
76
|
-
CapacitorHttp: { enabled: true },
|
|
77
|
-
Keyboard: { resize: "none" },
|
|
78
|
-
},
|
|
79
|
-
android: { flavor: "qa", path: "android" },
|
|
80
|
-
ios: { scheme: "App QA", path: "ios" },
|
|
81
|
-
cordova: { preferences: { ScrollEnabled: "false" } },
|
|
82
|
-
experimental: { ios: { spm: { swiftToolsVersion: "5.9" } } },
|
|
83
|
-
});
|
|
84
|
-
expect(config).not.toHaveProperty("name");
|
|
85
|
-
expect(config).not.toHaveProperty("basePath");
|
|
86
|
-
expect(config).not.toHaveProperty("indexPath");
|
|
87
|
-
expect(config).not.toHaveProperty("version");
|
|
88
|
-
expect(config).not.toHaveProperty("buildNum");
|
|
89
|
-
expect(config).not.toHaveProperty("assets");
|
|
90
|
-
expect(config).not.toHaveProperty("permissions");
|
|
91
|
-
expect(config).not.toHaveProperty("deepLinks");
|
|
92
|
-
expect(config).not.toHaveProperty("files");
|
|
93
|
-
expect(config).not.toHaveProperty("server");
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test("adds local server config without requiring env target switching", () => {
|
|
97
|
-
const config = materializeCapacitorConfig(
|
|
98
|
-
{
|
|
99
|
-
...baseTarget,
|
|
100
|
-
server: {
|
|
101
|
-
hostname: "localhost",
|
|
102
|
-
allowNavigation: ["api.example.com"],
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
operation: "local",
|
|
107
|
-
localIp: "192.168.0.5",
|
|
108
|
-
localServerUrl: "http://192.168.0.5:8282/en/admin?csr=true&akanMobileTarget=default",
|
|
109
|
-
},
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
expect(config.server).toEqual({
|
|
113
|
-
hostname: "localhost",
|
|
114
|
-
androidScheme: "http",
|
|
115
|
-
url: "http://192.168.0.5:8282/en/admin?csr=true&akanMobileTarget=default",
|
|
116
|
-
cleartext: true,
|
|
117
|
-
allowNavigation: ["api.example.com", "192.168.0.5", "localhost"],
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test("allows mobile targets to override the default keyboard resize mode", () => {
|
|
122
|
-
const config = materializeCapacitorConfig(
|
|
123
|
-
{
|
|
124
|
-
...baseTarget,
|
|
125
|
-
plugins: { Keyboard: { resize: "native" } },
|
|
126
|
-
},
|
|
127
|
-
{ operation: "release" },
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
expect(config.plugins).toMatchObject({
|
|
131
|
-
Keyboard: { resize: "native" },
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
test("rejects non-json config values", () => {
|
|
136
|
-
expect(() => assertJsonSerializable({ plugins: { Custom: () => null } })).toThrow("must be JSON serializable");
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
describe("root capacitor config helpers", () => {
|
|
141
|
-
test("clears root configs before writing the temporary json config", async () => {
|
|
142
|
-
const root = await makeTempRoot();
|
|
143
|
-
await Promise.all(rootCapacitorConfigFilenames.map((file) => writeFile(path.join(root, file), `old ${file}\n`)));
|
|
144
|
-
|
|
145
|
-
await writeRootCapacitorConfig(root, '{\n "appId": "com.minimal.app"\n}\n');
|
|
146
|
-
|
|
147
|
-
expect(await Bun.file(path.join(root, "capacitor.config.ts")).exists()).toBe(false);
|
|
148
|
-
expect(await Bun.file(path.join(root, "capacitor.config.js")).exists()).toBe(false);
|
|
149
|
-
expect(await Bun.file(path.join(root, "capacitor.config.json")).text()).toBe(
|
|
150
|
-
'{\n "appId": "com.minimal.app"\n}\n',
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
await clearRootCapacitorConfigs(root);
|
|
154
|
-
|
|
155
|
-
expect(await Bun.file(path.join(root, "capacitor.config.json")).exists()).toBe(false);
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
describe("iOS native run helpers", () => {
|
|
160
|
-
test("parses xcrun device and simulator outputs", () => {
|
|
161
|
-
expect(
|
|
162
|
-
parseDevicectlDevices(
|
|
163
|
-
JSON.stringify({
|
|
164
|
-
result: {
|
|
165
|
-
devices: [
|
|
166
|
-
{
|
|
167
|
-
identifier: "1BCB6563-02FF-5D49-9655-1BFF02A638D3",
|
|
168
|
-
connectionProperties: { pairingState: "paired", transportType: "wired", tunnelState: "available" },
|
|
169
|
-
deviceProperties: { name: "Seok iPhone" },
|
|
170
|
-
hardwareProperties: { udid: "00008130-000200113EC1001C" },
|
|
171
|
-
},
|
|
172
|
-
],
|
|
173
|
-
},
|
|
174
|
-
}),
|
|
175
|
-
),
|
|
176
|
-
).toEqual([
|
|
177
|
-
{
|
|
178
|
-
id: "00008130-000200113EC1001C",
|
|
179
|
-
name: "Seok iPhone",
|
|
180
|
-
kind: "device",
|
|
181
|
-
state: "available wired paired",
|
|
182
|
-
devicectlId: "1BCB6563-02FF-5D49-9655-1BFF02A638D3",
|
|
183
|
-
xcodebuildId: "00008130-000200113EC1001C",
|
|
184
|
-
},
|
|
185
|
-
]);
|
|
186
|
-
|
|
187
|
-
expect(
|
|
188
|
-
parseSimctlDevices(
|
|
189
|
-
JSON.stringify({
|
|
190
|
-
devices: {
|
|
191
|
-
"com.apple.CoreSimulator.SimRuntime.iOS-18-2": [
|
|
192
|
-
{ udid: "11111111-2222-3333-4444-555555555555", name: "iPhone 16", state: "Shutdown", isAvailable: true },
|
|
193
|
-
],
|
|
194
|
-
},
|
|
195
|
-
}),
|
|
196
|
-
),
|
|
197
|
-
).toEqual([
|
|
198
|
-
{
|
|
199
|
-
id: "11111111-2222-3333-4444-555555555555",
|
|
200
|
-
name: "iPhone 16",
|
|
201
|
-
kind: "simulator",
|
|
202
|
-
state: "Shutdown",
|
|
203
|
-
runtime: "iOS 18.2",
|
|
204
|
-
},
|
|
205
|
-
]);
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
test("sorts run targets so booted / connected / newest-runtime targets come first", () => {
|
|
209
|
-
const ios17 = { id: "a", name: "iPhone 15", kind: "simulator" as const, state: "Shutdown", runtime: "iOS 17.5" };
|
|
210
|
-
const ios18 = { id: "b", name: "iPhone 16", kind: "simulator" as const, state: "Shutdown", runtime: "iOS 18.2" };
|
|
211
|
-
const booted17 = { id: "c", name: "iPhone SE", kind: "simulator" as const, state: "Booted", runtime: "iOS 17.0" };
|
|
212
|
-
const device = { id: "d", name: "Seok iPhone", kind: "device" as const, state: "available wired paired" };
|
|
213
|
-
// Input is in the old ascending-runtime order that used to default to iOS 17.
|
|
214
|
-
const sorted = sortIosRunTargets([ios17, ios18, booted17, device]);
|
|
215
|
-
expect(sorted.map((t) => t.id)).toEqual(["d", "c", "b", "a"]);
|
|
216
|
-
// Newest available simulator beats the older one, so the interactive default is no longer iOS 17.
|
|
217
|
-
expect(sortIosRunTargets([ios17, ios18]).map((t) => t.id)).toEqual(["b", "a"]);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
test("parses the major iOS runtime version", () => {
|
|
221
|
-
expect(parseIosRuntimeMajor("iOS 18.2")).toBe(18);
|
|
222
|
-
expect(parseIosRuntimeMajor("iOS 17.5")).toBe(17);
|
|
223
|
-
expect(parseIosRuntimeMajor(undefined)).toBeUndefined();
|
|
224
|
-
expect(SWIFTUICORE_MIN_IOS_MAJOR).toBe(18);
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
test("builds xcodebuild destinations and output paths by target kind", () => {
|
|
228
|
-
const deviceCommand = buildIosNativeRunCommand({
|
|
229
|
-
appRoot: "/repo/apps/minimal",
|
|
230
|
-
device: { id: "device-1", name: "iPhone", kind: "device" },
|
|
231
|
-
scheme: "App QA",
|
|
232
|
-
configuration: "Debug",
|
|
233
|
-
});
|
|
234
|
-
expect(deviceCommand.xcodebuildArgs).toContain("id=device-1");
|
|
235
|
-
expect(deviceCommand.xcodebuildArgs).toContain("App QA");
|
|
236
|
-
expect(deviceCommand.appPath).toBe(
|
|
237
|
-
"/repo/apps/minimal/ios/DerivedData/device-1/Build/Products/Debug-iphoneos/App.app",
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
const simulatorCommand = buildIosNativeRunCommand({
|
|
241
|
-
appRoot: "/repo/apps/minimal",
|
|
242
|
-
device: { id: "sim-1", name: "Simulator", kind: "simulator" },
|
|
243
|
-
});
|
|
244
|
-
expect(simulatorCommand.xcodebuildArgs).toContain("platform=iOS Simulator,id=sim-1");
|
|
245
|
-
expect(simulatorCommand.appPath).toBe(
|
|
246
|
-
"/repo/apps/minimal/ios/DerivedData/sim-1/Build/Products/Debug-iphonesimulator/App.app",
|
|
247
|
-
);
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
test("classifies iOS signing and device-state failures", () => {
|
|
251
|
-
expect(classifyIosRunFailure("There are no accounts registered with Xcode").kind).toBe("apple-account");
|
|
252
|
-
expect(
|
|
253
|
-
classifyIosRunFailure(
|
|
254
|
-
'Failed Registering Bundle Identifier: The app identifier "com.minimal.app" cannot be registered to your development team',
|
|
255
|
-
).kind,
|
|
256
|
-
).toBe("bundle-identifier");
|
|
257
|
-
expect(classifyIosRunFailure("No profiles for 'com.minimal.app' were found").kind).toBe("provisioning-profile");
|
|
258
|
-
expect(classifyIosRunFailure("Developer Mode is disabled on this device").kind).toBe("device-state");
|
|
259
|
-
expect(classifyIosRunFailure("arm64-apple-darwin20.0: error: unknown argument: '-index-store-path'").kind).toBe(
|
|
260
|
-
"compiler-toolchain",
|
|
261
|
-
);
|
|
262
|
-
expect(
|
|
263
|
-
classifyIosRunFailure(
|
|
264
|
-
"dyld[1234]: Library not loaded: /System/Library/Frameworks/SwiftUICore.framework/SwiftUICore",
|
|
265
|
-
).kind,
|
|
266
|
-
).toBe("simulator-runtime");
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
test("removes shell compiler variables from iOS native run env", () => {
|
|
270
|
-
expect(
|
|
271
|
-
sanitizeIosNativeRunEnv({
|
|
272
|
-
AKAN_PUBLIC_APP_NAME: "minimal",
|
|
273
|
-
CC: "arm64-apple-darwin20.0.0-clang",
|
|
274
|
-
CXX: "arm64-apple-darwin20.0.0-clang++",
|
|
275
|
-
SDKROOT: "/wrong/sdk",
|
|
276
|
-
}),
|
|
277
|
-
).toEqual({ AKAN_PUBLIC_APP_NAME: "minimal" });
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
test("flags placeholder bundle identifiers that Apple's portal already claims", () => {
|
|
281
|
-
for (const appId of ["com.myapp.app", "com.myorg.myapp", "com.example.foo", "com.changeme.app", ""]) {
|
|
282
|
-
expect(isPlaceholderAppId(appId)).toBe(true);
|
|
283
|
-
}
|
|
284
|
-
for (const appId of ["com.minimal.app", "com.nearthlab.leadingflight", "io.akanjs.demo"]) {
|
|
285
|
-
expect(isPlaceholderAppId(appId)).toBe(false);
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
describe("selectLocalDevHost", () => {
|
|
291
|
-
const build = (map: Record<string, { family: string; address: string; internal?: boolean }[]>) =>
|
|
292
|
-
map as unknown as Parameters<typeof selectLocalDevHost>[0];
|
|
293
|
-
|
|
294
|
-
test("prefers a routable LAN NIC over an inactive bridge enumerated first", () => {
|
|
295
|
-
const resolution = selectLocalDevHost(
|
|
296
|
-
build({
|
|
297
|
-
bridge0: [{ family: "IPv4", address: "192.168.2.1" }],
|
|
298
|
-
en0: [{ family: "IPv4", address: "172.25.140.140" }],
|
|
299
|
-
bridge100: [{ family: "IPv4", address: "192.168.3.1" }],
|
|
300
|
-
en8: [{ family: "IPv4", address: "172.25.40.227" }],
|
|
301
|
-
}),
|
|
302
|
-
);
|
|
303
|
-
expect(resolution.host).toBe("172.25.140.140");
|
|
304
|
-
expect(resolution.source).toBe("detected");
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
test("an explicit override always wins and is trimmed", () => {
|
|
308
|
-
const resolution = selectLocalDevHost(build({ en0: [{ family: "IPv4", address: "172.25.140.140" }] }), {
|
|
309
|
-
override: " 10.0.0.9 ",
|
|
310
|
-
});
|
|
311
|
-
expect(resolution).toMatchObject({ host: "10.0.0.9", source: "override" });
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
test("never selects a link-local address when a real LAN address exists", () => {
|
|
315
|
-
const resolution = selectLocalDevHost(
|
|
316
|
-
build({
|
|
317
|
-
en0: [{ family: "IPv4", address: "169.254.10.10" }],
|
|
318
|
-
en1: [{ family: "IPv4", address: "192.168.1.5" }],
|
|
319
|
-
}),
|
|
320
|
-
);
|
|
321
|
-
expect(resolution.host).toBe("192.168.1.5");
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
test("falls back to loopback when nothing routable is present", () => {
|
|
325
|
-
const resolution = selectLocalDevHost(build({ lo0: [{ family: "IPv4", address: "127.0.0.1", internal: true }] }));
|
|
326
|
-
expect(resolution).toMatchObject({ host: "127.0.0.1", source: "loopback" });
|
|
327
|
-
});
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
describe("Android signing diagnostics", () => {
|
|
331
|
-
test("reports missing release signing keys and adb authorization issues", () => {
|
|
332
|
-
expect(
|
|
333
|
-
getMissingAndroidReleaseSigningKeys({
|
|
334
|
-
env: { MYAPP_RELEASE_STORE_FILE: "release.jks" } as NodeJS.ProcessEnv,
|
|
335
|
-
gradleProperties: "MYAPP_RELEASE_STORE_PASSWORD=secret\n",
|
|
336
|
-
}),
|
|
337
|
-
).toEqual(["MYAPP_RELEASE_KEY_ALIAS", "MYAPP_RELEASE_KEY_PASSWORD"]);
|
|
338
|
-
expect(formatAndroidReleaseSigningError(["MYAPP_RELEASE_KEY_ALIAS"])).toContain("MYAPP_RELEASE_KEY_ALIAS");
|
|
339
|
-
expect(getAdbDeviceStateIssues("List of devices attached\nabc123 unauthorized\nxyz offline\n")).toEqual([
|
|
340
|
-
"Android device abc123 is unauthorized. Confirm USB debugging authorization on the device.",
|
|
341
|
-
"Android device xyz is offline. Reconnect the device or restart adb.",
|
|
342
|
-
]);
|
|
343
|
-
expect(getAndroidLocalServerHost("List of devices attached\nemulator-5554 device\n", "192.168.0.5")).toBe(
|
|
344
|
-
"10.0.2.2",
|
|
345
|
-
);
|
|
346
|
-
expect(getAndroidLocalServerHost("List of devices attached\nabc123 device\n", "192.168.0.5")).toBe("192.168.0.5");
|
|
347
|
-
expect(
|
|
348
|
-
getAndroidLocalServerHost("List of devices attached\nemulator-5554 device\nabc123 device\n", "192.168.0.5"),
|
|
349
|
-
).toBe("192.168.0.5");
|
|
350
|
-
});
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
describe("raiseGradleMinSdkVersion", () => {
|
|
354
|
-
test("raises the scaffold minSdkVersion to the bundled-plugin floor, preserving formatting", () => {
|
|
355
|
-
const scaffold = "ext {\n minSdkVersion = 24\n compileSdkVersion = 35\n}\n";
|
|
356
|
-
expect(raiseGradleMinSdkVersion(scaffold)).toBe(
|
|
357
|
-
`ext {\n minSdkVersion = ${ANDROID_MIN_SDK_VERSION}\n compileSdkVersion = 35\n}\n`,
|
|
358
|
-
);
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
test("returns null when nothing needs changing", () => {
|
|
362
|
-
// Already at the floor, already above it, and no assignment present.
|
|
363
|
-
expect(raiseGradleMinSdkVersion(`ext {\n minSdkVersion = ${ANDROID_MIN_SDK_VERSION}\n}\n`)).toBeNull();
|
|
364
|
-
expect(raiseGradleMinSdkVersion("ext {\n minSdkVersion = 34\n}\n")).toBeNull();
|
|
365
|
-
expect(raiseGradleMinSdkVersion("ext {\n compileSdkVersion = 35\n}\n")).toBeNull();
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
test("honors an explicit floor and leaves higher user values untouched", () => {
|
|
369
|
-
expect(raiseGradleMinSdkVersion("minSdkVersion = 21", 23)).toBe("minSdkVersion = 23");
|
|
370
|
-
expect(raiseGradleMinSdkVersion("minSdkVersion = 28", 26)).toBeNull();
|
|
371
|
-
});
|
|
372
|
-
});
|