@akanjs/cli 3.0.0-beta.2 → 3.0.0-beta.20
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/.build-stamp +1 -1
- package/CodeAgent-awv258wb.js +9 -0
- package/CodeAgentRpcHost-p7h6n2hp.js +7 -0
- package/CodeAgentRpcListener-7p7z5dd7.js +97 -0
- package/CodeTui-1nqh35ez.js +1457 -0
- package/README.md +3 -0
- package/TunnelShare-scf4e4pd.js +9 -0
- package/{agent.command-d2gfxfck.js → agent.command-1s9ag7sb.js} +8 -9
- package/akanCode.js +102 -0
- package/{application.command-pj2m7584.js → application.command-49hwy6va.js} +51 -78
- package/{applicationBuildRunner-kxwbssgn.js → applicationBuildRunner-ybyp97pv.js} +63 -64
- package/{applicationReleasePackager-4yasxwv9.js → applicationReleasePackager-esnrphw8.js} +40 -60
- package/buildBatch.proc.js +19 -24
- package/{capacitorApp-36rbr858.js → capacitorApp-1synz4en.js} +3 -4
- package/cloud.command-d7rqtzt9.js +94 -0
- package/cloud.script-bkbpcr96.js +19 -0
- package/code.command-nn48xzej.js +154 -0
- package/commandManifest.json +1 -1
- package/consoleToStderr-h5bryj94.js +7 -0
- package/context.command-s3mcmvpa.js +48 -0
- package/context.runner-k99nb5pk.js +21 -0
- package/{dependencyScanner-shs82ynp.js → dependencyScanner-ye2e6pdz.js} +2 -2
- package/{devTui-40ggmd99.js → devTui-q7k7bakd.js} +122 -40
- package/fileSys-5ngz93ga.js +9 -0
- package/guideline.command-sct4qnt5.js +42 -0
- package/guidelines/agentRule/agentRule.instruction.md +206 -25
- package/guidelines/conventions/conventions.instruction.md +79 -24
- package/guidelines/fieldRule/fieldRule.instruction.md +1 -0
- package/guidelines/mcpRule/mcpRule.instruction.md +7 -5
- package/guidelines/queryRule/queryRule.instruction.md +17 -7
- package/guidelines/runtimeRule/runtimeRule.instruction.md +74 -0
- package/guidelines/ssrRule/ssrRule.instruction.md +4 -2
- package/guidelines/transportRule/transportRule.instruction.md +51 -0
- package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +66 -3
- package/incrementalBuilder.proc.js +31 -48
- package/{index-h7yw2z9n.js → index-0bq14vr1.js} +8 -14
- package/index-13ffe9wp.js +69 -0
- package/index-22d57v4c.js +266 -0
- package/{index-fz5q3gd7.js → index-31yr441d.js} +10 -17
- package/index-3hx1z96c.js +87 -0
- package/index-3sq321ak.js +53 -0
- package/{index-kcxmv48c.js → index-3t7g9e4r.js} +45 -79
- package/{index-q0y2jq9j.js → index-5b6tavv3.js} +6 -3
- package/{index-47pj3aee.js → index-5e0n4hqx.js} +11 -12
- package/{index-259dsnz3.js → index-5pc1qrbv.js} +5 -8
- package/index-7md2g9vw.js +6 -0
- package/index-8mna0947.js +187 -0
- package/{index-zry5nz81.js → index-8sf7wmdr.js} +51 -30
- package/{index-2tv3fdx4.js → index-9d9bgcx4.js} +342 -765
- package/index-9dp031by.js +12 -0
- package/{index-ne2qy0nk.js → index-ahemdr5n.js} +12 -12
- package/{index-ws5e0j51.js → index-as7xmyz8.js} +40 -24
- package/index-axzjaqve.js +1118 -0
- package/{index-3d9y066c.js → index-bjwxs904.js} +9 -8
- package/index-c6eggbee.js +123 -0
- package/index-d2242ksy.js +99 -0
- package/{index-a64esmtb.js → index-ddxvdd1p.js} +169 -305
- package/{index-92zztqy1.js → index-dy0jx9ay.js} +2 -17
- package/{index-pnqbkf5p.js → index-dzf3r49a.js} +6 -2
- package/{index-w8kmx1b6.js → index-fgq75haa.js} +198 -290
- package/{index-by5gpp8x.js → index-hj6w4ka1.js} +2 -1
- package/{index-hwkygn9s.js → index-khpfpcsd.js} +302 -33
- package/{index-wt7qrtd4.js → index-mxav6j3c.js} +93 -232
- package/{index-gyd220p2.js → index-myhc3c1j.js} +554 -577
- package/{index-600zhnve.js → index-nv5976x3.js} +56 -197
- package/index-p6pbz9n5.js +25 -0
- package/{index-4edzf1gr.js → index-przybvy5.js} +77 -150
- package/index-smme4r47.js +49 -0
- package/{index-mak3cd28.js → index-w2zdcw3k.js} +137 -255
- package/index-wa5jbxj1.js +760 -0
- package/{index-v0qh106m.js → index-ww4z397j.js} +527 -723
- package/{index-j9yhg404.js → index-xqjwd384.js} +4 -7
- package/{index-7737gxcp.js → index-xqpzbab5.js} +107 -241
- package/index-xsjh6nzh.js +2729 -0
- package/{index-ktb5njgy.js → index-ygn77a5w.js} +47 -99
- package/index-ztp3e73t.js +700 -0
- package/index.js +23 -22
- package/{library.command-nbsky672.js → library.command-1gx04jgn.js} +4 -5
- package/{localRegistry.command-yeq57wjr.js → localRegistry.command-zndxj1q6.js} +22 -42
- package/{module.command-29vqzrh8.js → module.command-3waddk95.js} +8 -11
- package/{package.command-axv0abmn.js → package.command-zrc7br1y.js} +6 -7
- package/package.json +14 -5
- package/{page.command-vs9s3zrh.js → page.command-vpjgardh.js} +4 -5
- package/{primitive.command-cbxmqbtc.js → primitive.command-sz84tk4t.js} +9 -22
- package/prompter-ptaa3nk0.js +8 -0
- package/{quality.command-gmbs7nws.js → quality.command-g869hafs.js} +203 -376
- package/{recipeScanner-fpagtgc1.js → recipeScanner-4b69ybe0.js} +1 -1
- package/{repair.command-bqsjptsj.js → repair.command-chsnjvvv.js} +11 -35
- package/{routeSourceValidator-apyqw7wk.js → routeSourceValidator-7ycnfz0e.js} +0 -6
- package/{scalar.command-6k1vhe9s.js → scalar.command-2v21newx.js} +7 -10
- package/skills/akan-code/SKILL.md +130 -0
- package/skills/akan-debug/SKILL.md +42 -0
- package/skills/akan-deps/SKILL.md +50 -0
- package/skills/akan-err/SKILL.md +39 -0
- package/skills/akan-module/SKILL.md +45 -0
- package/skills/akan-scaffold/SKILL.md +76 -0
- package/skills/akan-scalar/SKILL.md +52 -0
- package/skills/akan-service/SKILL.md +34 -0
- package/skills/akan-store/SKILL.md +67 -0
- package/skills/akan-ui/SKILL.md +63 -0
- package/skills/akan-validate/SKILL.md +44 -0
- package/{subspace.command-fwjfcts7.js → subspace.command-ckcbwfp1.js} +138 -67
- package/templates/__scalar/__model__/__model__.abstract.md.template +8 -0
- package/templates/appSample/lib/__scalar/workHistory/workHistory.abstract.ts +8 -39
- package/templates/appSample/lib/_noti/noti.abstract.ts +6 -29
- package/templates/appSample/lib/task/task.abstract.ts +12 -32
- package/templates/appSample/lib/task/task.signal.spec.ts +15 -18
- package/templates/appSample/lib/task/task.signal.test.ts +15 -1
- package/templates/appSample/lib/task/task.signal.ts +1 -1
- package/templates/appSample/srvkit/{AuthGuard.ts → guards.ts} +7 -4
- package/templates/appSample/srvkit/{SessionInternalArg.ts → internalArgs.ts} +6 -4
- package/templates/client.ts +7 -30
- package/templates/crudPages/[__model__Id]/edit/page.tsx +2 -1
- package/templates/crudPages/[__model__Id]/page.tsx +2 -1
- package/templates/crudPages/new/page.tsx +2 -1
- package/templates/crudPages/page.tsx +2 -1
- package/templates/crudSinglePage/page.tsx +2 -1
- package/templates/lib/__lib/lib.dictionary.ts +0 -2
- package/templates/lib/__lib/lib.document.ts +0 -2
- package/templates/lib/sig.ts +8 -30
- package/templates/localDev/docker-compose.yaml.template +3 -14
- package/templates/module/__model__.signal.ts +12 -4
- package/templates/pkgRoot/tsconfig.json.template +2 -7
- package/templates/server.ts +0 -2
- package/templates/service/__model__.abstract.md.template +8 -0
- package/tunnel.command-kd2yr4fx.js +129 -0
- package/{typeChecker-3xgrzc2v.js → typeChecker-px49mezc.js} +1 -1
- package/typecheck.proc.js +1 -1
- package/workflow.command-44252cqv.js +79 -0
- package/{workspace.command-8s050m0h.js → workspace.command-fqcztt5p.js} +77 -109
- package/abstractCompactor-mjh5ppsq.js +0 -101
- package/cloud.command-jshwdq22.js +0 -93
- package/context.command-ez8a0zyz.js +0 -80
- package/devTuiView-c08ccbat.js +0 -9
- package/getDirname-dr3jz1xg.js +0 -7
- package/guideline.command-xmqwx8zm.js +0 -359
- package/guidelines/agentRule/agentRule.generate.json +0 -31
- package/guidelines/componentRule/componentRule.generate.json +0 -31
- package/guidelines/conventions/conventions.generate.json +0 -25
- package/guidelines/cssRule/cssRule.generate.json +0 -31
- package/guidelines/docPageRule/docPageRule.generate.json +0 -31
- package/guidelines/docPageRule/docPageRule.instruction.md +0 -25
- package/guidelines/docSyncRule/docSyncRule.generate.json +0 -31
- package/guidelines/docSyncRule/docSyncRule.instruction.md +0 -25
- package/guidelines/enumConstant/enumConstant.generate.json +0 -31
- package/guidelines/enumConstant/enumConstant.instruction.md +0 -28
- package/guidelines/fieldRule/fieldRule.generate.json +0 -31
- package/guidelines/framework/framework.generate.json +0 -32
- package/guidelines/mcpRule/mcpRule.generate.json +0 -35
- package/guidelines/modelConstant/modelConstant.generate.json +0 -32
- package/guidelines/modelDictionary/modelDictionary.generate.json +0 -32
- package/guidelines/modelDocument/modelDocument.generate.json +0 -31
- package/guidelines/modelService/modelService.generate.json +0 -31
- package/guidelines/modelSignal/modelSignal.generate.json +0 -31
- package/guidelines/modelStore/modelStore.generate.json +0 -31
- package/guidelines/modelTemplate/modelTemplate.generate.json +0 -31
- package/guidelines/modelUnit/modelUnit.generate.json +0 -31
- package/guidelines/modelUtil/modelUtil.generate.json +0 -31
- package/guidelines/modelView/modelView.generate.json +0 -31
- package/guidelines/modelZone/modelZone.generate.json +0 -31
- package/guidelines/moduleCodegen/moduleCodegen.generate.json +0 -31
- package/guidelines/moduleCodegen/moduleCodegen.instruction.md +0 -28
- package/guidelines/moduleOverview/moduleOverview.generate.json +0 -31
- package/guidelines/queryRule/queryRule.generate.json +0 -31
- package/guidelines/recipeRule/recipeRule.generate.json +0 -31
- package/guidelines/runtimeRule/runtimeRule.generate.json +0 -25
- package/guidelines/scalarConstant/scalarConstant.generate.json +0 -32
- package/guidelines/scalarDictionary/scalarDictionary.generate.json +0 -32
- package/guidelines/scalarModule/scalarModule.generate.json +0 -31
- package/guidelines/sharedUiUsage/sharedUiUsage.generate.json +0 -31
- package/guidelines/sharedUiUsage/sharedUiUsage.instruction.md +0 -25
- package/guidelines/ssrRule/ssrRule.generate.json +0 -31
- package/guidelines/transportRule/transportRule.generate.json +0 -31
- package/guidelines/utilUiUsage/utilUiUsage.generate.json +0 -31
- package/guidelines/utilUiUsage/utilUiUsage.instruction.md +0 -25
- package/guidelines/workspaceOnboarding/workspaceOnboarding.generate.json +0 -24
- package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +0 -33
- package/index-2hq52jq3.js +0 -465
- package/index-6wwzs1bc.js +0 -7
- package/index-8pm30m73.js +0 -841
- package/index-kn1h7p1x.js +0 -560
- package/index-meh558jy.js +0 -65
- package/index-rwg2aa4f.js +0 -229
- package/templates/__scalar/__model__/__model__.abstract.md +0 -28
- package/templates/module/__model__.abstract.md +0 -28
- package/templates/service/__model__.abstract.md +0 -28
- package/workflow.command-nwpcdc8p.js +0 -107
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
CommandExecutionError
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-9d9bgcx4.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveMobilePath,
|
|
7
7
|
targetHtmlFilename
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-5e0n4hqx.js";
|
|
9
9
|
|
|
10
10
|
// pkgs/@akanjs/devkit/capacitorApp.ts
|
|
11
11
|
import { cp, mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
@@ -13,7 +13,7 @@ import os from "os";
|
|
|
13
13
|
import path from "path";
|
|
14
14
|
import { select } from "@inquirer/prompts";
|
|
15
15
|
import { MobileProject } from "@trapezedev/project";
|
|
16
|
-
import { capitalize } from "akanjs/common";
|
|
16
|
+
import { capitalize, isRecord } from "akanjs/common";
|
|
17
17
|
|
|
18
18
|
// pkgs/@akanjs/devkit/fileEditor.ts
|
|
19
19
|
class FileEditor {
|
|
@@ -32,52 +32,28 @@ class FileEditor {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
find(pattern) {
|
|
35
|
-
const lines = this.#content.split(`
|
|
36
|
-
`);
|
|
37
35
|
const regex = typeof pattern === "string" ? new RegExp(pattern) : pattern;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (!line)
|
|
41
|
-
continue;
|
|
42
|
-
if (regex.test(line))
|
|
43
|
-
return i;
|
|
44
|
-
}
|
|
45
|
-
return -1;
|
|
36
|
+
return this.#content.split(`
|
|
37
|
+
`).findIndex((line) => !!line && regex.test(line));
|
|
46
38
|
}
|
|
47
39
|
findAll(pattern) {
|
|
48
|
-
const lines = this.#content.split(`
|
|
49
|
-
`);
|
|
50
40
|
const regex = typeof pattern === "string" ? new RegExp(pattern) : pattern;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const line = lines[i];
|
|
54
|
-
if (!line)
|
|
55
|
-
continue;
|
|
56
|
-
if (regex.test(line))
|
|
57
|
-
matches.push(i);
|
|
58
|
-
}
|
|
59
|
-
return matches;
|
|
41
|
+
return this.#content.split(`
|
|
42
|
+
`).flatMap((line, index) => line && regex.test(line) ? [index] : []);
|
|
60
43
|
}
|
|
61
44
|
insertAfter(pattern, data) {
|
|
62
|
-
|
|
63
|
-
if (lineIndex === -1) {
|
|
64
|
-
throw new Error(`Pattern not found: ${pattern}`);
|
|
65
|
-
}
|
|
66
|
-
const lines = this.#content.split(`
|
|
67
|
-
`);
|
|
68
|
-
lines.splice(lineIndex + 1, 0, data);
|
|
69
|
-
this.#content = lines.join(`
|
|
70
|
-
`);
|
|
71
|
-
return this;
|
|
45
|
+
return this.#insertAt(pattern, data, 1);
|
|
72
46
|
}
|
|
73
47
|
insertBefore(pattern, data) {
|
|
48
|
+
return this.#insertAt(pattern, data, 0);
|
|
49
|
+
}
|
|
50
|
+
#insertAt(pattern, data, offset) {
|
|
74
51
|
const lineIndex = this.find(pattern);
|
|
75
|
-
if (lineIndex === -1)
|
|
52
|
+
if (lineIndex === -1)
|
|
76
53
|
throw new Error(`Pattern not found: ${pattern}`);
|
|
77
|
-
}
|
|
78
54
|
const lines = this.#content.split(`
|
|
79
55
|
`);
|
|
80
|
-
lines.splice(lineIndex, 0, data);
|
|
56
|
+
lines.splice(lineIndex + offset, 0, data);
|
|
81
57
|
this.#content = lines.join(`
|
|
82
58
|
`);
|
|
83
59
|
return this;
|
|
@@ -115,30 +91,7 @@ ${this.#content}`;
|
|
|
115
91
|
|
|
116
92
|
// pkgs/@akanjs/devkit/capacitorApp.ts
|
|
117
93
|
var SWIFTUICORE_MIN_IOS_MAJOR = 18;
|
|
118
|
-
var iosNativeBlockedEnvKeys = new Set(
|
|
119
|
-
"AR",
|
|
120
|
-
"AS",
|
|
121
|
-
"CC",
|
|
122
|
-
"CFLAGS",
|
|
123
|
-
"CONDA_BUILD_SYSROOT",
|
|
124
|
-
"CONDA_PREFIX",
|
|
125
|
-
"CPP",
|
|
126
|
-
"CPPFLAGS",
|
|
127
|
-
"CPATH",
|
|
128
|
-
"CXX",
|
|
129
|
-
"CXXFLAGS",
|
|
130
|
-
"LD",
|
|
131
|
-
"LDFLAGS",
|
|
132
|
-
"LIBRARY_PATH",
|
|
133
|
-
"MACOSX_DEPLOYMENT_TARGET",
|
|
134
|
-
"NM",
|
|
135
|
-
"OBJC",
|
|
136
|
-
"OBJCXX",
|
|
137
|
-
"PREFIX",
|
|
138
|
-
"RANLIB",
|
|
139
|
-
"SDKROOT",
|
|
140
|
-
"STRIP"
|
|
141
|
-
]);
|
|
94
|
+
var iosNativeBlockedEnvKeys = new Set("AR AS CC CFLAGS CONDA_BUILD_SYSROOT CONDA_PREFIX CPP CPPFLAGS CPATH CXX CXXFLAGS LD LDFLAGS LIBRARY_PATH".split(" ").concat("MACOSX_DEPLOYMENT_TARGET NM OBJC OBJCXX PREFIX RANLIB SDKROOT STRIP".split(" ")));
|
|
142
95
|
var rootCapacitorConfigFilenames = [
|
|
143
96
|
"capacitor.config.ts",
|
|
144
97
|
"capacitor.config.js",
|
|
@@ -152,22 +105,7 @@ async function writeRootCapacitorConfig(appRoot, content) {
|
|
|
152
105
|
await clearRootCapacitorConfigs(appRoot);
|
|
153
106
|
await Bun.write(path.join(appRoot, "capacitor.config.json"), content);
|
|
154
107
|
}
|
|
155
|
-
var virtualInterfacePrefixes =
|
|
156
|
-
"bridge",
|
|
157
|
-
"utun",
|
|
158
|
-
"llw",
|
|
159
|
-
"awdl",
|
|
160
|
-
"ap",
|
|
161
|
-
"vmnet",
|
|
162
|
-
"vnic",
|
|
163
|
-
"tap",
|
|
164
|
-
"tun",
|
|
165
|
-
"docker",
|
|
166
|
-
"veth",
|
|
167
|
-
"vboxnet",
|
|
168
|
-
"gif",
|
|
169
|
-
"stf"
|
|
170
|
-
];
|
|
108
|
+
var virtualInterfacePrefixes = "bridge utun llw awdl ap vmnet vnic tap tun docker veth vboxnet gif stf".split(" ");
|
|
171
109
|
var physicalInterfacePrefixes = ["en", "eth", "wlan", "wlp", "enp", "eno", "wlo"];
|
|
172
110
|
var isPrivateLanIpv4 = (address) => {
|
|
173
111
|
if (address.startsWith("10.") || address.startsWith("192.168."))
|
|
@@ -203,7 +141,6 @@ var selectLocalDevHost = (interfaces, { override } = {}) => {
|
|
|
203
141
|
const [best] = [...candidates].sort((a, b) => scoreDevHostCandidate(b.name, b.address) - scoreDevHostCandidate(a.name, a.address) || a.name.localeCompare(b.name) || a.address.localeCompare(b.address));
|
|
204
142
|
return best ? { host: best.address, source: "detected", candidates } : { host: "127.0.0.1", source: "loopback", candidates };
|
|
205
143
|
};
|
|
206
|
-
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
207
144
|
var asString = (value) => typeof value === "string" ? value : undefined;
|
|
208
145
|
var firstString = (...values) => values.find((value) => typeof value === "string");
|
|
209
146
|
var scoreIosDeviceTarget = (target) => {
|
|
@@ -232,11 +169,8 @@ var formatSimctlRuntime = (key) => {
|
|
|
232
169
|
return `${match[1]} ${match[2]}${match[3] ? `.${match[3]}` : ""}`;
|
|
233
170
|
};
|
|
234
171
|
var parseIosRuntimeMajor = (runtime) => {
|
|
235
|
-
const major = runtime?.match(
|
|
236
|
-
|
|
237
|
-
return;
|
|
238
|
-
const parsed = Number.parseInt(major, 10);
|
|
239
|
-
return Number.isNaN(parsed) ? undefined : parsed;
|
|
172
|
+
const major = runtime?.match(/\d+/)?.[0];
|
|
173
|
+
return major === undefined ? undefined : Number.parseInt(major, 10);
|
|
240
174
|
};
|
|
241
175
|
var iosRunTargetRank = (target) => {
|
|
242
176
|
const state = target.state?.toLowerCase() ?? "";
|
|
@@ -450,7 +384,7 @@ function classifyIosRunFailure(log) {
|
|
|
450
384
|
return {
|
|
451
385
|
kind: "unknown",
|
|
452
386
|
title: "iOS native run failed.",
|
|
453
|
-
detail: "Review the xcodebuild/devicectl output above. You can retry with --
|
|
387
|
+
detail: "Review the xcodebuild/devicectl output above. You can retry with --no-allow-provisioning-updates to use the conservative path."
|
|
454
388
|
};
|
|
455
389
|
}
|
|
456
390
|
function formatIosRunFailureMessage(input) {
|
|
@@ -528,6 +462,20 @@ function raiseGradleMinSdkVersion(content, floor = ANDROID_MIN_SDK_VERSION) {
|
|
|
528
462
|
return null;
|
|
529
463
|
return content.replace(/(minSdkVersion\s*=\s*)\d+/, `$1${floor}`);
|
|
530
464
|
}
|
|
465
|
+
var iosUsageDescriptionKeys = {
|
|
466
|
+
cameraUsageDescription: ["NSCameraUsageDescription"],
|
|
467
|
+
photoAddUsageDescription: ["NSPhotoLibraryAddUsageDescription"],
|
|
468
|
+
photoUsageDescription: ["NSPhotoLibraryUsageDescription"],
|
|
469
|
+
contactsUsageDescription: ["NSContactsUsageDescription"],
|
|
470
|
+
locationAlwaysUsageDescription: ["NSLocationAlwaysAndWhenInUseUsageDescription", "NSLocationAlwaysUsageDescription"],
|
|
471
|
+
locationWhenInUseUsageDescription: ["NSLocationWhenInUseUsageDescription"],
|
|
472
|
+
microphoneUsageDescription: ["NSMicrophoneUsageDescription"],
|
|
473
|
+
speechRecognitionUsageDescription: ["NSSpeechRecognitionUsageDescription"]
|
|
474
|
+
};
|
|
475
|
+
var toIosInfoPlistUsageDescriptions = (descriptions) => Object.fromEntries(Object.entries(descriptions).flatMap(([key, value]) => {
|
|
476
|
+
const plistKeys = Object.hasOwn(iosUsageDescriptionKeys, key) ? iosUsageDescriptionKeys[key] : [`NS${capitalize(key)}`];
|
|
477
|
+
return plistKeys.map((plistKey) => [plistKey, value]);
|
|
478
|
+
}));
|
|
531
479
|
var mergeAllowNavigation = (configured, localIp) => {
|
|
532
480
|
const values = Array.isArray(configured) ? configured.filter((value) => typeof value === "string") : [];
|
|
533
481
|
if (localIp)
|
|
@@ -552,9 +500,8 @@ function assertJsonSerializable(value, label = "capacitor.config", seen = new We
|
|
|
552
500
|
throw new Error(`${label} must be JSON serializable. Found circular reference.`);
|
|
553
501
|
seen.add(objectValue);
|
|
554
502
|
if (Array.isArray(value)) {
|
|
555
|
-
|
|
503
|
+
for (const [index, item] of value.entries())
|
|
556
504
|
assertJsonSerializable(item, `${label}[${index}]`, seen);
|
|
557
|
-
});
|
|
558
505
|
return;
|
|
559
506
|
}
|
|
560
507
|
for (const [key, item] of Object.entries(value)) {
|
|
@@ -715,7 +662,6 @@ class CapacitorApp2 {
|
|
|
715
662
|
await this.#prepareIos({ operation: "release", env, regenerate });
|
|
716
663
|
await this.#spawnMobile("npx", ["cap", "build", "ios"], { operation: "release", env }, { stdio: "inherit" });
|
|
717
664
|
this.app.verbose(`build completed iOS.`);
|
|
718
|
-
return;
|
|
719
665
|
}
|
|
720
666
|
async syncIos() {
|
|
721
667
|
await this.#spawnMobile("npx", ["cap", "sync", "ios"], { operation: "local", env: "local" });
|
|
@@ -735,7 +681,10 @@ class CapacitorApp2 {
|
|
|
735
681
|
await this.#runIosPhysicalDevice({ operation, env, runTarget, noAllowProvisioningUpdates });
|
|
736
682
|
}
|
|
737
683
|
async#selectIosRunTarget(deviceId) {
|
|
738
|
-
const targets = sortIosRunTargets(
|
|
684
|
+
const targets = sortIosRunTargets([
|
|
685
|
+
...await this.#loadPhysicalIosDevices(),
|
|
686
|
+
...await this.#loadIosSimulators()
|
|
687
|
+
]);
|
|
739
688
|
if (deviceId) {
|
|
740
689
|
const needle = deviceId.toLowerCase();
|
|
741
690
|
const found = targets.find((target) => target.id === deviceId) ?? targets.find((target) => target.name.toLowerCase() === needle) ?? targets.find((target) => target.name.toLowerCase().includes(needle) || target.id.toLowerCase().includes(needle) || (target.runtime?.toLowerCase().includes(needle) ?? false));
|
|
@@ -767,11 +716,6 @@ class CapacitorApp2 {
|
|
|
767
716
|
return;
|
|
768
717
|
this.app.logger.warn(`Selected simulator runs ${target.runtime ?? "an older iOS"}. Recent SDK builds link SwiftUICore and require iOS ${SWIFTUICORE_MIN_IOS_MAJOR}+; if the app crashes at launch with a "Library not loaded: SwiftUICore" dyld error, pick an iOS ${SWIFTUICORE_MIN_IOS_MAJOR}+ simulator instead.`);
|
|
769
718
|
}
|
|
770
|
-
async#loadIosRunTargets() {
|
|
771
|
-
const devices = await this.#loadPhysicalIosDevices();
|
|
772
|
-
const simulators = await this.#loadIosSimulators();
|
|
773
|
-
return [...devices, ...simulators];
|
|
774
|
-
}
|
|
775
719
|
async#loadPhysicalIosDevices() {
|
|
776
720
|
try {
|
|
777
721
|
return parseDevicectlDevices(await this.#spawn("xcrun", ["devicectl", "list", "devices", "--json-output", "-"]));
|
|
@@ -806,12 +750,11 @@ ${textError instanceof Error ? textError.message : ""}`);
|
|
|
806
750
|
}) {
|
|
807
751
|
const mobileEnv = sanitizeIosNativeRunEnv(await this.#commandEnv(operation, env));
|
|
808
752
|
const configContent = await this.#writeCapacitorConfig({ operation, platform: "ios", iosRunTargetKind: runTarget.kind }, mobileEnv);
|
|
809
|
-
await
|
|
810
|
-
const scheme = this.#iosScheme();
|
|
753
|
+
await writeRootCapacitorConfig(this.app.cwdPath, configContent);
|
|
811
754
|
const command = buildIosNativeRunCommand({
|
|
812
755
|
appRoot: this.app.cwdPath,
|
|
813
756
|
device: runTarget,
|
|
814
|
-
scheme,
|
|
757
|
+
scheme: isRecord(this.target.ios) && typeof this.target.ios.scheme === "string" ? this.target.ios.scheme : "App",
|
|
815
758
|
configuration: operation === "release" ? "Release" : "Debug"
|
|
816
759
|
});
|
|
817
760
|
const xcodebuildArgs = noAllowProvisioningUpdates ? command.xcodebuildArgs : [...command.xcodebuildArgs.slice(0, -1), "-allowProvisioningUpdates", ...command.xcodebuildArgs.slice(-1)];
|
|
@@ -821,12 +764,9 @@ ${textError instanceof Error ? textError.message : ""}`);
|
|
|
821
764
|
env: mobileEnv
|
|
822
765
|
});
|
|
823
766
|
const devicectlId = runTarget.devicectlId ?? runTarget.id;
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
await this.#spawn("xcrun", ["devicectl", "device", "process", "launch", "--device", devicectlId, this.target.appId], {
|
|
828
|
-
env: mobileEnv
|
|
829
|
-
});
|
|
767
|
+
const devicectl = (verb, subject) => this.#spawn("xcrun", ["devicectl", "device", ...verb, "--device", devicectlId, subject], { env: mobileEnv });
|
|
768
|
+
await devicectl(["install", "app"], command.appPath);
|
|
769
|
+
await devicectl(["process", "launch"], this.target.appId);
|
|
830
770
|
} catch (error) {
|
|
831
771
|
throw new Error(formatIosRunFailureMessage({
|
|
832
772
|
classification: classifyIosRunFailure(this.#errorOutput(error)),
|
|
@@ -835,12 +775,9 @@ ${textError instanceof Error ? textError.message : ""}`);
|
|
|
835
775
|
teamId: await this.#getIosDevelopmentTeam()
|
|
836
776
|
}));
|
|
837
777
|
} finally {
|
|
838
|
-
await
|
|
778
|
+
await clearRootCapacitorConfigs(this.app.cwdPath);
|
|
839
779
|
}
|
|
840
780
|
}
|
|
841
|
-
#iosScheme() {
|
|
842
|
-
return isRecord(this.target.ios) && typeof this.target.ios.scheme === "string" ? this.target.ios.scheme : "App";
|
|
843
|
-
}
|
|
844
781
|
async#getIosDevelopmentTeam() {
|
|
845
782
|
const pbxprojPath = path.join(this.app.cwdPath, this.iosProjectPath, "App.xcodeproj/project.pbxproj");
|
|
846
783
|
if (!await Bun.file(pbxprojPath).exists())
|
|
@@ -865,7 +802,7 @@ ${error.message}`;
|
|
|
865
802
|
await this.#disableNativeKeyboardResizeInAndroid();
|
|
866
803
|
await this.project.commit();
|
|
867
804
|
await this.#generateAssets({ operation, env });
|
|
868
|
-
await this
|
|
805
|
+
await mkdir(path.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
|
|
869
806
|
await this.#ensureAndroidDebugKeystore();
|
|
870
807
|
await this.#spawnMobile("npx", ["cap", "sync", "android"], { operation, env });
|
|
871
808
|
await this.#setDeepLinksInAndroid(this.target.deepLinks?.schemes ?? [], this.target.deepLinks?.domains ?? []);
|
|
@@ -911,8 +848,7 @@ ${error.message}`;
|
|
|
911
848
|
await this.#prepareAndroid({ operation: "release", env, regenerate });
|
|
912
849
|
await this.#assertAndroidReleaseSigningConfig();
|
|
913
850
|
await this.#updateAndroidBuildTypes();
|
|
914
|
-
const
|
|
915
|
-
const gradleCommand = isWindows ? "gradlew.bat" : "./gradlew";
|
|
851
|
+
const gradleCommand = process.platform === "win32" ? "gradlew.bat" : "./gradlew";
|
|
916
852
|
await this.app.spawn(gradleCommand, [assembleType === "apk" ? "assembleRelease" : "bundleRelease"], {
|
|
917
853
|
stdio: "inherit",
|
|
918
854
|
cwd: path.join(this.app.cwdPath, this.androidRootPath),
|
|
@@ -939,30 +875,17 @@ ${error.message}`;
|
|
|
939
875
|
if (changed)
|
|
940
876
|
await writeFile(manifestPath, manifest);
|
|
941
877
|
}
|
|
942
|
-
async#ensureAndroidAssetsDir() {
|
|
943
|
-
await mkdir(path.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
|
|
944
|
-
}
|
|
945
878
|
async#ensureAndroidDebugKeystore() {
|
|
946
879
|
const keystorePath = path.join(this.app.cwdPath, this.androidRootPath, "app/debug.keystore");
|
|
947
880
|
if (await Bun.file(keystorePath).exists())
|
|
948
881
|
return;
|
|
882
|
+
const options = "-storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000";
|
|
949
883
|
await this.#spawn("keytool", [
|
|
950
884
|
"-genkeypair",
|
|
951
885
|
"-v",
|
|
952
886
|
"-keystore",
|
|
953
887
|
keystorePath,
|
|
954
|
-
"
|
|
955
|
-
"android",
|
|
956
|
-
"-alias",
|
|
957
|
-
"androiddebugkey",
|
|
958
|
-
"-keypass",
|
|
959
|
-
"android",
|
|
960
|
-
"-keyalg",
|
|
961
|
-
"RSA",
|
|
962
|
-
"-keysize",
|
|
963
|
-
"2048",
|
|
964
|
-
"-validity",
|
|
965
|
-
"10000",
|
|
888
|
+
...options.split(" "),
|
|
966
889
|
"-dname",
|
|
967
890
|
"CN=Android Debug,O=Android,C=US"
|
|
968
891
|
]);
|
|
@@ -978,8 +901,7 @@ ${error.message}`;
|
|
|
978
901
|
await this.#prepareAndroid({ operation, env, regenerate });
|
|
979
902
|
await this.#assertAndroidAdbReady();
|
|
980
903
|
this.app.logger.info(`Running Android in ${operation} mode on ${env} env`);
|
|
981
|
-
|
|
982
|
-
await this.#spawnMobile("npx", args, { operation, env }, { stdio: "inherit" });
|
|
904
|
+
await this.#spawnMobile("npx", ["cap", "run", "android"], { operation, env }, { stdio: "inherit" });
|
|
983
905
|
}
|
|
984
906
|
async#assertAndroidReleaseSigningConfig() {
|
|
985
907
|
const gradlePropertiesPath = path.join(this.app.cwdPath, this.androidRootPath, "gradle.properties");
|
|
@@ -1086,14 +1008,12 @@ ${error.message}`;
|
|
|
1086
1008
|
if (!this.target.assets)
|
|
1087
1009
|
return;
|
|
1088
1010
|
await mkdir(this.targetAssetRoot, { recursive: true });
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
force: true
|
|
1096
|
-
});
|
|
1011
|
+
for (const [name, source] of [
|
|
1012
|
+
["icon", this.target.assets.icon],
|
|
1013
|
+
["splash", this.target.assets.splash]
|
|
1014
|
+
])
|
|
1015
|
+
if (source)
|
|
1016
|
+
await cp(path.join(this.app.cwdPath, source), path.join(this.targetAssetRoot, `${name}.png`), { force: true });
|
|
1097
1017
|
}
|
|
1098
1018
|
async#prepareExternalFiles(platform) {
|
|
1099
1019
|
const files = this.target.files?.[platform];
|
|
@@ -1179,20 +1099,11 @@ ${error.message}`;
|
|
|
1179
1099
|
operation,
|
|
1180
1100
|
env,
|
|
1181
1101
|
setIosUsageDescriptions: (descriptions) => this.#setPermissionInIos(descriptions),
|
|
1182
|
-
updateIosInfoPlist:
|
|
1183
|
-
await Promise.all([
|
|
1184
|
-
this.project.ios.updateInfoPlist(this.iosTargetName, "Debug", values),
|
|
1185
|
-
this.project.ios.updateInfoPlist(this.iosTargetName, "Release", values)
|
|
1186
|
-
]);
|
|
1187
|
-
},
|
|
1102
|
+
updateIosInfoPlist: (values) => this.#updateIosInfoPlist(values),
|
|
1188
1103
|
addIosEntitlements: (entitlements) => this.#addIosEntitlements(entitlements),
|
|
1189
1104
|
editIosAppDelegate: (transform) => this.#editIosAppDelegate(transform),
|
|
1190
|
-
addAndroidPermissions: (permissions) =>
|
|
1191
|
-
|
|
1192
|
-
},
|
|
1193
|
-
addAndroidFeatures: (features) => {
|
|
1194
|
-
this.#setFeaturesInAndroid(features);
|
|
1195
|
-
}
|
|
1105
|
+
addAndroidPermissions: (permissions) => this.#setPermissionsInAndroid(permissions),
|
|
1106
|
+
addAndroidFeatures: (features) => this.#setFeaturesInAndroid(features)
|
|
1196
1107
|
};
|
|
1197
1108
|
}
|
|
1198
1109
|
async#applyDeepLinks(platform, { operation, env }) {
|
|
@@ -1263,12 +1174,6 @@ ${error.message}`;
|
|
|
1263
1174
|
params.set("akanMobileIndexPath", this.target.indexPath);
|
|
1264
1175
|
return `http://${ip}:${port}/${pathname}?${params}`;
|
|
1265
1176
|
}
|
|
1266
|
-
async#clearRootCapacitorConfigs() {
|
|
1267
|
-
await clearRootCapacitorConfigs(this.app.cwdPath);
|
|
1268
|
-
}
|
|
1269
|
-
async#writeRootCapacitorConfig(content) {
|
|
1270
|
-
await writeRootCapacitorConfig(this.app.cwdPath, content);
|
|
1271
|
-
}
|
|
1272
1177
|
async#spawn(command, args = [], options = {}) {
|
|
1273
1178
|
return await this.app.spawn(command, args, { cwd: this.app.cwdPath, ...options });
|
|
1274
1179
|
}
|
|
@@ -1276,14 +1181,11 @@ ${error.message}`;
|
|
|
1276
1181
|
const { iosRunTargetKind, platform, ...spawnOptions } = options;
|
|
1277
1182
|
const mobileEnv = { ...await this.#commandEnv(operation, env), ...options.env };
|
|
1278
1183
|
const configContent = await this.#writeCapacitorConfig({ operation, platform: platform ?? this.#inferMobilePlatform(args), iosRunTargetKind }, mobileEnv);
|
|
1279
|
-
await
|
|
1184
|
+
await writeRootCapacitorConfig(this.app.cwdPath, configContent);
|
|
1280
1185
|
try {
|
|
1281
|
-
return await this.#spawn(command, args, {
|
|
1282
|
-
...spawnOptions,
|
|
1283
|
-
env: mobileEnv
|
|
1284
|
-
});
|
|
1186
|
+
return await this.#spawn(command, args, { ...spawnOptions, env: mobileEnv });
|
|
1285
1187
|
} finally {
|
|
1286
|
-
await
|
|
1188
|
+
await clearRootCapacitorConfigs(this.app.cwdPath);
|
|
1287
1189
|
}
|
|
1288
1190
|
}
|
|
1289
1191
|
#inferMobilePlatform(args) {
|
|
@@ -1328,22 +1230,16 @@ ${error.message}`;
|
|
|
1328
1230
|
if (next !== content)
|
|
1329
1231
|
await editor.setContent(next).save();
|
|
1330
1232
|
}
|
|
1233
|
+
async#updateIosInfoPlist(values) {
|
|
1234
|
+
await Promise.all(["Debug", "Release"].map((build) => this.project.ios.updateInfoPlist(this.iosTargetName, build, values)));
|
|
1235
|
+
}
|
|
1331
1236
|
async#setPermissionInIos(permissions) {
|
|
1332
|
-
|
|
1333
|
-
await Promise.all([
|
|
1334
|
-
this.project.ios.updateInfoPlist(this.iosTargetName, "Debug", updateNs),
|
|
1335
|
-
this.project.ios.updateInfoPlist(this.iosTargetName, "Release", updateNs)
|
|
1336
|
-
]);
|
|
1237
|
+
await this.#updateIosInfoPlist(toIosInfoPlistUsageDescriptions(permissions));
|
|
1337
1238
|
}
|
|
1338
1239
|
async#setUrlSchemesInIos(schemes) {
|
|
1339
|
-
|
|
1340
|
-
CFBundleURLName: this.target.appId,
|
|
1341
|
-
|
|
1342
|
-
}));
|
|
1343
|
-
await Promise.all([
|
|
1344
|
-
this.project.ios.updateInfoPlist(this.iosTargetName, "Debug", { CFBundleURLTypes: urlTypes }),
|
|
1345
|
-
this.project.ios.updateInfoPlist(this.iosTargetName, "Release", { CFBundleURLTypes: urlTypes })
|
|
1346
|
-
]);
|
|
1240
|
+
await this.#updateIosInfoPlist({
|
|
1241
|
+
CFBundleURLTypes: schemes.map((scheme) => ({ CFBundleURLName: this.target.appId, CFBundleURLSchemes: [scheme] }))
|
|
1242
|
+
});
|
|
1347
1243
|
}
|
|
1348
1244
|
#serializeIosEntitlements(entitlements) {
|
|
1349
1245
|
const lines = [];
|
|
@@ -1419,97 +1315,62 @@ ${error.message}`;
|
|
|
1419
1315
|
return;
|
|
1420
1316
|
await this.#setCodeSignEntitlementsInIos(entitlementsRelPath);
|
|
1421
1317
|
}
|
|
1422
|
-
async#
|
|
1318
|
+
async#setDeepLinksInAndroid(schemes, domains) {
|
|
1423
1319
|
const manifestPath = path.join(this.app.cwdPath, this.androidRootPath, "app/src/main/AndroidManifest.xml");
|
|
1424
|
-
|
|
1425
|
-
|
|
1320
|
+
const original = await readFile(manifestPath, "utf8");
|
|
1321
|
+
const pathPrefix = resolveMobilePath(this.target, "/");
|
|
1322
|
+
let manifest = original;
|
|
1426
1323
|
for (const scheme of schemes) {
|
|
1427
1324
|
if (manifest.includes(`android:scheme="${scheme}"`))
|
|
1428
1325
|
continue;
|
|
1429
|
-
|
|
1430
|
-
" <intent-filter>",
|
|
1431
|
-
' <action android:name="android.intent.action.VIEW" />',
|
|
1432
|
-
' <category android:name="android.intent.category.DEFAULT" />',
|
|
1433
|
-
' <category android:name="android.intent.category.BROWSABLE" />',
|
|
1434
|
-
` <data android:scheme="${scheme}" />`,
|
|
1435
|
-
" </intent-filter>"
|
|
1436
|
-
].join(`
|
|
1437
|
-
`);
|
|
1438
|
-
manifest = manifest.replace(/(\s*<\/activity>)/, `
|
|
1439
|
-
${filter}$1`);
|
|
1440
|
-
changed = true;
|
|
1326
|
+
manifest = CapacitorApp2.#withIntentFilter(manifest, "<intent-filter>", `<data android:scheme="${scheme}" />`);
|
|
1441
1327
|
}
|
|
1442
|
-
if (changed)
|
|
1443
|
-
await writeFile(manifestPath, manifest);
|
|
1444
|
-
}
|
|
1445
|
-
async#setDeepLinksInAndroid(schemes, domains) {
|
|
1446
|
-
await this.#setUrlSchemesInAndroid(schemes);
|
|
1447
|
-
const manifestPath = path.join(this.app.cwdPath, this.androidRootPath, "app/src/main/AndroidManifest.xml");
|
|
1448
|
-
let manifest = await readFile(manifestPath, "utf8");
|
|
1449
|
-
let changed = false;
|
|
1450
|
-
const pathPrefix = resolveMobilePath(this.target, "/");
|
|
1451
1328
|
for (const domain of domains) {
|
|
1452
1329
|
if (manifest.includes(`android:host="${domain}"`) && manifest.includes('android:scheme="https"'))
|
|
1453
1330
|
continue;
|
|
1454
|
-
|
|
1455
|
-
' <intent-filter android:autoVerify="true">',
|
|
1456
|
-
' <action android:name="android.intent.action.VIEW" />',
|
|
1457
|
-
' <category android:name="android.intent.category.DEFAULT" />',
|
|
1458
|
-
' <category android:name="android.intent.category.BROWSABLE" />',
|
|
1459
|
-
` <data android:scheme="https" android:host="${domain}" android:pathPrefix="${pathPrefix}" />`,
|
|
1460
|
-
" </intent-filter>"
|
|
1461
|
-
].join(`
|
|
1462
|
-
`);
|
|
1463
|
-
manifest = manifest.replace(/(\s*<\/activity>)/, `
|
|
1464
|
-
${filter}$1`);
|
|
1465
|
-
changed = true;
|
|
1331
|
+
manifest = CapacitorApp2.#withIntentFilter(manifest, '<intent-filter android:autoVerify="true">', `<data android:scheme="https" android:host="${domain}" android:pathPrefix="${pathPrefix}" />`);
|
|
1466
1332
|
}
|
|
1467
|
-
if (
|
|
1333
|
+
if (manifest !== original)
|
|
1468
1334
|
await writeFile(manifestPath, manifest);
|
|
1469
1335
|
}
|
|
1336
|
+
static #withIntentFilter(manifest, open, data) {
|
|
1337
|
+
const filter = [
|
|
1338
|
+
` ${open}`,
|
|
1339
|
+
' <action android:name="android.intent.action.VIEW" />',
|
|
1340
|
+
' <category android:name="android.intent.category.DEFAULT" />',
|
|
1341
|
+
' <category android:name="android.intent.category.BROWSABLE" />',
|
|
1342
|
+
` ${data}`,
|
|
1343
|
+
" </intent-filter>"
|
|
1344
|
+
].join(`
|
|
1345
|
+
`);
|
|
1346
|
+
return manifest.replace(/(\s*<\/activity>)/, `
|
|
1347
|
+
${filter}$1`);
|
|
1348
|
+
}
|
|
1470
1349
|
#setFeaturesInAndroid(features) {
|
|
1471
1350
|
for (const feature of features) {
|
|
1472
|
-
if (this.#
|
|
1351
|
+
if (this.#androidManifestNames("uses-feature").includes(feature)) {
|
|
1473
1352
|
this.app.logger.info(`${feature} already exists in android`);
|
|
1474
|
-
return
|
|
1353
|
+
return;
|
|
1475
1354
|
}
|
|
1476
1355
|
this.app.logger.info(`Adding ${feature} to android`);
|
|
1477
1356
|
this.project.android.getAndroidManifest().injectFragment("manifest", `<uses-feature android:name="${feature}" />`);
|
|
1478
1357
|
}
|
|
1479
|
-
return this;
|
|
1480
|
-
}
|
|
1481
|
-
#getFeaturesInAndroid() {
|
|
1482
|
-
const androidManifest = this.project.android.getAndroidManifest();
|
|
1483
|
-
const element = androidManifest.getDocumentElement();
|
|
1484
|
-
if (!element)
|
|
1485
|
-
throw new Error("manifest not found");
|
|
1486
|
-
const usesFeature = element.getElementsByTagName("uses-feature");
|
|
1487
|
-
return Array.from(usesFeature).map((feature) => feature.getAttribute("android:name"));
|
|
1488
|
-
}
|
|
1489
|
-
#hasFeatureInAndroid(feature) {
|
|
1490
|
-
return this.#getFeaturesInAndroid().includes(feature);
|
|
1491
1358
|
}
|
|
1492
1359
|
#setPermissionsInAndroid(permissions) {
|
|
1493
1360
|
for (const permission of permissions) {
|
|
1494
|
-
if (this.#
|
|
1361
|
+
if (this.#androidManifestNames("uses-permission").includes(`android.permission.${permission}`)) {
|
|
1495
1362
|
this.app.logger.info(`${permission} already exists in android`);
|
|
1496
1363
|
continue;
|
|
1497
1364
|
}
|
|
1498
1365
|
this.app.logger.info(`Adding ${permission} to android`);
|
|
1499
1366
|
this.project.android.getAndroidManifest().injectFragment("manifest", `<uses-permission android:name="android.permission.${permission}" />`);
|
|
1500
1367
|
}
|
|
1501
|
-
return this;
|
|
1502
1368
|
}
|
|
1503
|
-
#
|
|
1504
|
-
const
|
|
1505
|
-
const element = androidManifest.getDocumentElement();
|
|
1369
|
+
#androidManifestNames(tagName) {
|
|
1370
|
+
const element = this.project.android.getAndroidManifest().getDocumentElement();
|
|
1506
1371
|
if (!element)
|
|
1507
1372
|
throw new Error("manifest not found");
|
|
1508
|
-
|
|
1509
|
-
return Array.from(usesPermission).map((permission) => permission.getAttribute("android:name"));
|
|
1510
|
-
}
|
|
1511
|
-
#hasPermissionInAndroid(permission) {
|
|
1512
|
-
return this.#getPermissionsInAndroid().includes(`android.permission.${permission}`);
|
|
1373
|
+
return Array.from(element.getElementsByTagName(tagName)).map((node) => node.getAttribute("android:name"));
|
|
1513
1374
|
}
|
|
1514
1375
|
}
|
|
1515
1376
|
|