@akanjs/devkit 3.0.0-alpha.1 → 3.0.0-alpha.100
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/CHANGELOG.md +15 -0
- package/DEV_RUNTIME_KNOBS.md +34 -0
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/agentsIndex.test.ts +10 -0
- package/agentsIndex.ts +47 -1
- package/aiEditor.ts +1 -1
- package/akanApp/BackendImportGraph.test.ts +120 -0
- package/akanApp/BackendImportGraph.ts +167 -0
- package/akanApp/akanApp.host.test.ts +16 -678
- package/akanApp/akanApp.host.ts +113 -578
- package/akanApp/devHostPolicy.test.ts +542 -0
- package/akanApp/devHostPolicy.ts +442 -0
- package/akanApp/index.ts +2 -0
- package/akanConfig/akanConfig.test.ts +182 -14
- package/akanConfig/akanConfig.ts +143 -47
- package/akanConfig/types.ts +9 -0
- package/akanContext.ts +70 -42
- package/akanMcpContract.ts +25 -4
- package/appSelectionMemory.ts +28 -0
- package/applicationBuildRunner.test.ts +37 -2
- package/applicationBuildRunner.ts +53 -24
- package/artifact/implicitRootLayout.test.ts +67 -0
- package/artifact/implicitRootLayout.ts +27 -7
- package/artifact/routeSeedIndex.test.ts +1 -0
- package/biome.base.json +340 -0
- package/biomeBase.ts +9 -0
- package/capacitorApp.test.ts +8 -0
- package/capacitorApp.ts +122 -18
- package/cloud/globalConfig.ts +9 -2
- package/codegenLock.test.ts +137 -0
- package/codegenLock.ts +136 -0
- package/commandDecorators/argMeta.ts +9 -1
- package/commandDecorators/command.ts +94 -7
- package/commandDecorators/commandBuilder.ts +20 -5
- package/commandDecorators/commandDecorators.test.ts +115 -3
- package/commandDecorators/helpFormatter.ts +4 -0
- package/dependencyScanner.test.ts +99 -0
- package/dependencyScanner.ts +27 -24
- package/devkitUtils.test.ts +0 -104
- package/executors.test.ts +137 -5
- package/executors.ts +116 -26
- package/fileEditor.ts +19 -19
- package/fileSys.ts +19 -1
- package/formSetterScanner.test.ts +80 -0
- package/formSetterScanner.ts +92 -0
- package/frontendBuild/allRoutesBuilder.ts +27 -8
- package/frontendBuild/autoImportSync.test.ts +58 -0
- package/frontendBuild/autoImportSync.ts +7 -2
- package/frontendBuild/buildRouteClient.test.ts +47 -24
- package/frontendBuild/clientBuildTypes.ts +4 -0
- package/frontendBuild/clientEntriesBundler.ts +4 -1
- package/frontendBuild/clientEntryDiscovery.ts +2 -2
- package/frontendBuild/csrArtifactBuilder.ts +116 -84
- package/frontendBuild/cssCandidateCache.test.ts +38 -0
- package/frontendBuild/cssCandidateCache.ts +15 -3
- package/frontendBuild/cssCompiler.ts +123 -12
- package/frontendBuild/cssImportResolver.ts +8 -7
- package/frontendBuild/devGeneratedIndexSync.ts +3 -2
- package/frontendBuild/fontOptimizer.ts +37 -18
- package/frontendBuild/fontPruner.test.ts +220 -0
- package/frontendBuild/fontPruner.ts +206 -0
- package/frontendBuild/frontendBuild.test.ts +178 -10
- package/frontendBuild/hmrWatcher.ts +1 -1
- package/frontendBuild/index.ts +1 -1
- package/frontendBuild/pagesBundleBuilder.ts +3 -3
- package/frontendBuild/pagesEntrySourceGenerator.ts +11 -88
- package/frontendBuild/precompressArtifacts.ts +35 -7
- package/frontendBuild/routeClientBuilder.ts +26 -7
- package/frontendBuild/sourceMtimeIndex.ts +1 -1
- package/frontendBuild/ssrBaseArtifactBuilder.ts +21 -4
- package/frontendBuild/styleContract.ts +14 -20
- package/frontendBuild/themeValidator.ts +22 -17
- package/frontendBuild/vendorSpecifiers.ts +1 -0
- package/frontendBuild/watchRootResolver.test.ts +129 -0
- package/frontendBuild/watchRootResolver.ts +66 -1
- package/incrementalBuilder/devWatchBatch.test.ts +18 -20
- package/incrementalBuilder/devWatchBatch.ts +6 -2
- package/incrementalBuilder/incrementalBuilder.host.ts +51 -7
- package/incrementalBuilder/incrementalBuilder.proc.ts +17 -6
- package/index.ts +0 -7
- package/integration/devStabilityHarness.ts +2 -10
- package/libSource.test.ts +112 -0
- package/libSource.ts +126 -0
- package/lint/__fixtures__/README.md +40 -0
- package/lint/__fixtures__/no-arbitrary-color/bad.tsx +3 -0
- package/lint/__fixtures__/no-arbitrary-color/good.tsx +4 -0
- package/lint/__fixtures__/no-async-component-in-ui/bad.tsx +4 -0
- package/lint/__fixtures__/no-async-component-in-ui/good.tsx +4 -0
- package/lint/__fixtures__/no-bang-comment-in-client/bad.tsx +4 -0
- package/lint/__fixtures__/no-bang-comment-in-client/fixture.json +1 -0
- package/lint/__fixtures__/no-bang-comment-in-client/good.tsx +3 -0
- package/lint/__fixtures__/no-daisyui-legacy-class/bad.tsx +7 -0
- package/lint/__fixtures__/no-daisyui-legacy-class/good.tsx +5 -0
- package/lint/__fixtures__/no-deep-internal-import/bad.tsx +3 -0
- package/lint/__fixtures__/no-deep-internal-import/fixture.json +1 -0
- package/lint/__fixtures__/no-deep-internal-import/good.tsx +3 -0
- package/lint/__fixtures__/no-deprecated-log-level/bad.tsx +4 -0
- package/lint/__fixtures__/no-deprecated-log-level/good.tsx +4 -0
- package/lint/__fixtures__/no-import-client-functions/bad.tsx +2 -0
- package/lint/__fixtures__/no-import-client-functions/good.tsx +4 -0
- package/lint/__fixtures__/no-import-client-in-server/bad.tsx +6 -0
- package/lint/__fixtures__/no-import-client-in-server/good.tsx +5 -0
- package/lint/__fixtures__/no-import-external-library/bad.tsx +4 -0
- package/lint/__fixtures__/no-import-external-library/good.tsx +5 -0
- package/lint/__fixtures__/no-import-server-in-client/bad.tsx +6 -0
- package/lint/__fixtures__/no-import-server-in-client/good.tsx +4 -0
- package/lint/__fixtures__/no-init-fetch-in-client/store-file/bad.ts +1 -0
- package/lint/__fixtures__/no-init-fetch-in-client/store-file/fixture.json +1 -0
- package/lint/__fixtures__/no-init-fetch-in-client/store-file/good.ts +1 -0
- package/lint/__fixtures__/no-init-fetch-in-client/use-client/bad.tsx +4 -0
- package/lint/__fixtures__/no-init-fetch-in-client/use-client/good.tsx +5 -0
- package/lint/__fixtures__/no-inline-color/bad.tsx +3 -0
- package/lint/__fixtures__/no-inline-color/good.tsx +3 -0
- package/lint/__fixtures__/no-interpolated-arbitrary-class/bad.tsx +3 -0
- package/lint/__fixtures__/no-interpolated-arbitrary-class/good.tsx +3 -0
- package/lint/__fixtures__/no-js-private-class-method/bad.tsx +3 -0
- package/lint/__fixtures__/no-js-private-class-method/good.tsx +3 -0
- package/lint/__fixtures__/no-model-type-in-util-zone/bad.tsx +3 -0
- package/lint/__fixtures__/no-model-type-in-util-zone/good.tsx +6 -0
- package/lint/__fixtures__/no-raw-palette-class/bad.tsx +6 -0
- package/lint/__fixtures__/no-raw-palette-class/good.tsx +8 -0
- package/lint/__fixtures__/no-redeclare-predefined-endpoint/bad.ts +10 -0
- package/lint/__fixtures__/no-redeclare-predefined-endpoint/fixture.json +1 -0
- package/lint/__fixtures__/no-redeclare-predefined-endpoint/good.ts +6 -0
- package/lint/__fixtures__/no-return-in-store-action/bad.tsx +2 -0
- package/lint/__fixtures__/no-return-in-store-action/good.tsx +6 -0
- package/lint/__fixtures__/no-throw-raw-error/bad.tsx +4 -0
- package/lint/__fixtures__/no-throw-raw-error/good.tsx +4 -0
- package/lint/__fixtures__/no-unpublished-form-setter/bad.tsx +3 -0
- package/lint/__fixtures__/no-unpublished-form-setter/good.tsx +5 -0
- package/lint/__fixtures__/no-use-client-in-server/bad.tsx +3 -0
- package/lint/__fixtures__/no-use-client-in-server/good.tsx +2 -0
- package/lint/__fixtures__/non-scalar-props-restricted/bad.tsx +5 -0
- package/lint/__fixtures__/non-scalar-props-restricted/good.tsx +4 -0
- package/lint/gritRules.test.ts +178 -0
- package/lint/no-arbitrary-color.grit +1 -1
- package/lint/no-async-component-in-ui.grit +35 -0
- package/lint/no-bang-comment-in-client.grit +33 -0
- package/lint/no-daisyui-legacy-class.grit +26 -9
- package/lint/no-deprecated-log-level.grit +17 -0
- package/lint/no-import-client-in-server.grit +48 -0
- package/lint/no-import-server-in-client.grit +45 -0
- package/lint/no-init-fetch-in-client.grit +47 -0
- package/lint/no-inline-color.grit +10 -8
- package/lint/no-interpolated-arbitrary-class.grit +3 -3
- package/lint/no-model-type-in-util-zone.grit +58 -0
- package/lint/no-raw-palette-class.grit +3 -3
- package/lint/no-return-in-store-action.grit +35 -0
- package/lint/no-unpublished-form-setter.grit +41 -0
- package/lint/non-scalar-props-restricted.grit +16 -7
- package/linter.test.ts +80 -0
- package/linter.ts +99 -25
- package/package.json +6 -8
- package/prompter.ts +9 -4
- package/qualityScanner.test.ts +130 -0
- package/qualityScanner.ts +91 -62
- package/recipeScanner.ts +4 -1
- package/repoIdentity.ts +42 -0
- package/routeSourceValidator.test.ts +41 -0
- package/routeSourceValidator.ts +2 -44
- package/scanInfo.ts +32 -67
- package/semver.test.ts +26 -0
- package/semver.ts +31 -0
- package/slicePlanner.test.ts +182 -0
- package/slicePlanner.ts +235 -0
- package/ssrScanner.test.ts +301 -0
- package/subspace.test.ts +418 -0
- package/subspace.ts +723 -0
- package/subspaceConfig.ts +76 -0
- package/transforms/asyncDefaultExportDetector.ts +103 -0
- package/transforms/barrelImportsPlugin.ts +1 -1
- package/transforms/externalizeFrameworkPlugin.ts +0 -1
- package/transforms/transforms.test.ts +5 -5
- package/transforms/tsconfigPackageResolver.test.ts +230 -0
- package/tsconfig.json +6 -2
- package/typeChecker.ts +1 -1
- package/types.ts +1 -0
- package/uploadRelease.ts +2 -2
- package/workflow/executor.test.ts +146 -0
- package/workspaceLayout.test.ts +78 -0
- package/workspaceLayout.ts +106 -0
- package/builder.ts +0 -164
- package/extractDeps.ts +0 -86
- package/frontendBuild/styleGuard.test.ts +0 -165
- package/frontendBuild/styleGuard.ts +0 -322
- package/getCredentials.ts +0 -19
- package/getModelFileData.ts +0 -62
- package/src/capacitorApp.ts +0 -282
- package/streamAi.ts +0 -45
- package/ui/MultiScrollList.tsx +0 -242
- package/ui/ScrollList.tsx +0 -107
- package/ui/index.ts +0 -2
- package/useStdoutDimensions.ts +0 -20
package/biome.base.json
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.5.12/schema.json",
|
|
3
|
+
"vcs": {
|
|
4
|
+
"enabled": true,
|
|
5
|
+
"clientKind": "git",
|
|
6
|
+
"useIgnoreFile": false
|
|
7
|
+
},
|
|
8
|
+
"formatter": {
|
|
9
|
+
"enabled": true,
|
|
10
|
+
"indentStyle": "space",
|
|
11
|
+
"indentWidth": 2,
|
|
12
|
+
"lineWidth": 120
|
|
13
|
+
},
|
|
14
|
+
"linter": {
|
|
15
|
+
"enabled": true,
|
|
16
|
+
"rules": {
|
|
17
|
+
"preset": "recommended",
|
|
18
|
+
"suspicious": {
|
|
19
|
+
"noConsole": {
|
|
20
|
+
"level": "error",
|
|
21
|
+
"options": {
|
|
22
|
+
"allow": ["assert", "error", "info", "warn"]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"noArrayIndexKey": "off",
|
|
26
|
+
"noShadowRestrictedNames": "off",
|
|
27
|
+
"noUnnecessaryConditions": {
|
|
28
|
+
"level": "warn"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"correctness": {
|
|
32
|
+
"noUnusedFunctionParameters": "off",
|
|
33
|
+
"noUnusedImports": {
|
|
34
|
+
"level": "error",
|
|
35
|
+
"fix": "safe"
|
|
36
|
+
},
|
|
37
|
+
"useParseIntRadix": "off",
|
|
38
|
+
"useExhaustiveDependencies": "off",
|
|
39
|
+
"useHookAtTopLevel": "off"
|
|
40
|
+
},
|
|
41
|
+
"nursery": {
|
|
42
|
+
"useSortedClasses": {
|
|
43
|
+
"level": "error",
|
|
44
|
+
"fix": "safe",
|
|
45
|
+
"options": {
|
|
46
|
+
"attributes": ["classList"],
|
|
47
|
+
"functions": ["cn"]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"a11y": "off",
|
|
52
|
+
"complexity": {
|
|
53
|
+
"noStaticOnlyClass": "off"
|
|
54
|
+
},
|
|
55
|
+
"style": {
|
|
56
|
+
"useTemplate": {
|
|
57
|
+
"level": "warn",
|
|
58
|
+
"fix": "safe"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"domains": {
|
|
63
|
+
"project": "recommended",
|
|
64
|
+
"react": "recommended",
|
|
65
|
+
"test": "recommended",
|
|
66
|
+
"types": "all"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"javascript": {
|
|
70
|
+
"parser": {
|
|
71
|
+
"unsafeParameterDecoratorsEnabled": true
|
|
72
|
+
},
|
|
73
|
+
"formatter": {
|
|
74
|
+
"quoteStyle": "double"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"assist": {
|
|
78
|
+
"enabled": true,
|
|
79
|
+
"actions": {
|
|
80
|
+
"source": {
|
|
81
|
+
"organizeImports": "on"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"overrides": [
|
|
86
|
+
{
|
|
87
|
+
"includes": [
|
|
88
|
+
"**/env.client.local.ts",
|
|
89
|
+
"**/env.client.debug.ts",
|
|
90
|
+
"**/env.client.develop.ts",
|
|
91
|
+
"**/env.client.main.ts",
|
|
92
|
+
"**/env.client.testing.ts",
|
|
93
|
+
"**/env.server.local.ts",
|
|
94
|
+
"**/env.server.develop.ts",
|
|
95
|
+
"**/env.server.main.ts",
|
|
96
|
+
"**/env.server.testing.ts",
|
|
97
|
+
"**/env.server.type.ts",
|
|
98
|
+
"apps/*/lib/cnst.ts",
|
|
99
|
+
"apps/*/lib/dict.ts",
|
|
100
|
+
"apps/*/lib/db.ts",
|
|
101
|
+
"apps/*/lib/srv.ts",
|
|
102
|
+
"apps/*/lib/st.ts",
|
|
103
|
+
"apps/*/lib/sig.ts",
|
|
104
|
+
"apps/*/lib/useClient.ts",
|
|
105
|
+
"apps/*/lib/useServer.ts",
|
|
106
|
+
"apps/*/client.ts",
|
|
107
|
+
"apps/*/server.ts",
|
|
108
|
+
"apps/*/lib/*/index.tsx",
|
|
109
|
+
"libs/*/lib/cnst.ts",
|
|
110
|
+
"libs/*/lib/dict.ts",
|
|
111
|
+
"libs/*/lib/db.ts",
|
|
112
|
+
"libs/*/lib/srv.ts",
|
|
113
|
+
"libs/*/lib/st.ts",
|
|
114
|
+
"libs/*/lib/sig.ts",
|
|
115
|
+
"libs/*/lib/useClient.ts",
|
|
116
|
+
"libs/*/lib/useServer.ts",
|
|
117
|
+
"libs/*/client.ts",
|
|
118
|
+
"libs/*/server.ts",
|
|
119
|
+
"libs/*/index.ts",
|
|
120
|
+
"libs/*/lib/*/index.tsx",
|
|
121
|
+
"apps/*/lib/__lib/**",
|
|
122
|
+
"libs/*/lib/__lib/**"
|
|
123
|
+
],
|
|
124
|
+
"linter": { "enabled": false },
|
|
125
|
+
"formatter": { "enabled": false },
|
|
126
|
+
"assist": { "enabled": false }
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"includes": [
|
|
130
|
+
"apps/**/*.ts",
|
|
131
|
+
"apps/**/*.tsx",
|
|
132
|
+
"libs/**/*.ts",
|
|
133
|
+
"libs/**/*.tsx",
|
|
134
|
+
"!**/*.test.ts",
|
|
135
|
+
"!**/*.test.tsx",
|
|
136
|
+
"!**/*.spec.ts",
|
|
137
|
+
"!**/*.spec.tsx",
|
|
138
|
+
"!**/*.constant.ts",
|
|
139
|
+
"!**/common/**",
|
|
140
|
+
"!**/env/**"
|
|
141
|
+
],
|
|
142
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-throw-raw-error.grit"]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"includes": [
|
|
146
|
+
"{apps,libs}/**/page/**/*.ts",
|
|
147
|
+
"{apps,libs}/**/page/**/*.tsx",
|
|
148
|
+
"{apps,libs}/**/*.Unit.tsx",
|
|
149
|
+
"{apps,libs}/**/*.View.tsx"
|
|
150
|
+
],
|
|
151
|
+
"plugins": [
|
|
152
|
+
"./node_modules/@akanjs/devkit/lint/no-import-client-functions.grit",
|
|
153
|
+
"./node_modules/@akanjs/devkit/lint/no-use-client-in-server.grit"
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"includes": ["{apps,libs}/**/page/**/*.ts", "{apps,libs}/**/page/**/*.tsx"],
|
|
158
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/non-scalar-props-restricted.grit"]
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"includes": [
|
|
162
|
+
"{apps,libs}/**/*.constant.ts",
|
|
163
|
+
"{apps,libs}/**/*.document.ts",
|
|
164
|
+
"{apps,libs}/**/*.service.ts",
|
|
165
|
+
"{apps,libs}/**/*.store.ts"
|
|
166
|
+
],
|
|
167
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-js-private-class-method.grit"]
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"includes": ["{apps,libs}/**/*.store.ts"],
|
|
171
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-return-in-store-action.grit"]
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"includes": ["{apps,libs}/**/*.ts", "{apps,libs}/**/*.tsx"],
|
|
175
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-deprecated-log-level.grit"]
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"includes": ["{apps,libs}/**/*.signal.ts"],
|
|
179
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-redeclare-predefined-endpoint.grit"]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"includes": ["{apps,libs}/**/*.Util.tsx", "{apps,libs}/**/*.Zone.tsx"],
|
|
183
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-model-type-in-util-zone.grit"]
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"includes": ["{apps,libs}/**/ui/**/*.tsx", "!**/*.test.tsx", "!**/*.spec.tsx"],
|
|
187
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-async-component-in-ui.grit"]
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"includes": ["{apps,libs}/**/*.tsx", "!**/*.test.tsx", "!**/*.spec.tsx"],
|
|
191
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-unpublished-form-setter.grit"]
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"includes": [
|
|
195
|
+
"{apps,libs}/**/*.ts",
|
|
196
|
+
"{apps,libs}/**/*.tsx",
|
|
197
|
+
"!**/*.test.ts",
|
|
198
|
+
"!**/*.test.tsx",
|
|
199
|
+
"!**/*.spec.ts",
|
|
200
|
+
"!**/*.spec.tsx"
|
|
201
|
+
],
|
|
202
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-init-fetch-in-client.grit"]
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"includes": [
|
|
206
|
+
"**/ui/**/*.ts",
|
|
207
|
+
"**/ui/**/*.tsx",
|
|
208
|
+
"**/webkit/**/*.ts",
|
|
209
|
+
"**/webkit/**/*.tsx",
|
|
210
|
+
"**/common/**/*.ts",
|
|
211
|
+
"**/page/**/*.tsx",
|
|
212
|
+
"**/*.constant.ts",
|
|
213
|
+
"**/*.store.ts",
|
|
214
|
+
"**/*.Template.tsx",
|
|
215
|
+
"**/*.Unit.tsx",
|
|
216
|
+
"**/*.Util.tsx",
|
|
217
|
+
"**/*.View.tsx",
|
|
218
|
+
"**/*.Zone.tsx",
|
|
219
|
+
"!**/*.test.ts",
|
|
220
|
+
"!**/*.test.tsx",
|
|
221
|
+
"!**/*.spec.ts",
|
|
222
|
+
"!**/*.spec.tsx"
|
|
223
|
+
],
|
|
224
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-bang-comment-in-client.grit"]
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"includes": [
|
|
228
|
+
"{apps,libs}/**/*.constant.ts",
|
|
229
|
+
"{apps,libs}/**/*.dictionary.ts",
|
|
230
|
+
"{apps,libs}/**/*.document.ts",
|
|
231
|
+
"{apps,libs}/**/*.service.ts",
|
|
232
|
+
"{apps,libs}/**/*.signal.ts",
|
|
233
|
+
"{apps,libs}/**/*.store.ts",
|
|
234
|
+
"{apps,libs}/**/*.Template.tsx",
|
|
235
|
+
"{apps,libs}/**/*.Unit.tsx",
|
|
236
|
+
"{apps,libs}/**/*.Util.tsx",
|
|
237
|
+
"{apps,libs}/**/*.View.tsx",
|
|
238
|
+
"{apps,libs}/**/*.Zone.tsx"
|
|
239
|
+
],
|
|
240
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-deep-internal-import.grit"]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"includes": [
|
|
244
|
+
"{apps,libs}/**/page/**/*.ts",
|
|
245
|
+
"{apps,libs}/**/page/**/*.tsx",
|
|
246
|
+
"{apps,libs}/**/index.ts",
|
|
247
|
+
"{apps,libs}/**/index.tsx",
|
|
248
|
+
"{apps,libs}/**/cnst.ts",
|
|
249
|
+
"{apps,libs}/**/db.ts",
|
|
250
|
+
"{apps,libs}/**/dict.ts",
|
|
251
|
+
"{apps,libs}/**/option.ts",
|
|
252
|
+
"{apps,libs}/**/sig.ts",
|
|
253
|
+
"{apps,libs}/**/srv.ts",
|
|
254
|
+
"{apps,libs}/**/st.ts",
|
|
255
|
+
"{apps,libs}/**/*.constant.ts",
|
|
256
|
+
"{apps,libs}/**/*.dictionary.ts",
|
|
257
|
+
"{apps,libs}/**/*.document.ts",
|
|
258
|
+
"{apps,libs}/**/*.service.ts",
|
|
259
|
+
"{apps,libs}/**/*.signal.ts",
|
|
260
|
+
"{apps,libs}/**/*.signal.test.ts",
|
|
261
|
+
"{apps,libs}/**/*.service.test.ts",
|
|
262
|
+
"{apps,libs}/**/*.store.ts",
|
|
263
|
+
"{apps,libs}/**/*.Template.tsx",
|
|
264
|
+
"{apps,libs}/**/*.Unit.tsx",
|
|
265
|
+
"{apps,libs}/**/*.Util.tsx",
|
|
266
|
+
"{apps,libs}/**/*.View.tsx",
|
|
267
|
+
"{apps,libs}/**/*.Zone.tsx"
|
|
268
|
+
],
|
|
269
|
+
"plugins": [
|
|
270
|
+
"./node_modules/@akanjs/devkit/lint/no-import-external-library.grit",
|
|
271
|
+
"./node_modules/@akanjs/devkit/lint/no-deep-internal-import.grit"
|
|
272
|
+
]
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"includes": [
|
|
276
|
+
"apps/**/*.tsx",
|
|
277
|
+
"libs/**/*.tsx",
|
|
278
|
+
"apps/**/ui/**/*.ts",
|
|
279
|
+
"libs/**/ui/**/*.ts",
|
|
280
|
+
"apps/**/webkit/**/*.ts",
|
|
281
|
+
"libs/**/webkit/**/*.ts",
|
|
282
|
+
"apps/**/page/**/*.ts",
|
|
283
|
+
"libs/**/page/**/*.ts",
|
|
284
|
+
"apps/**/common/**/*.ts",
|
|
285
|
+
"libs/**/common/**/*.ts",
|
|
286
|
+
"apps/**/*.store.ts",
|
|
287
|
+
"libs/**/*.store.ts",
|
|
288
|
+
"apps/**/*.constant.ts",
|
|
289
|
+
"libs/**/*.constant.ts",
|
|
290
|
+
"!**/*.test.ts",
|
|
291
|
+
"!**/*.test.tsx",
|
|
292
|
+
"!**/*.spec.ts",
|
|
293
|
+
"!**/*.spec.tsx"
|
|
294
|
+
],
|
|
295
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-import-server-in-client.grit"]
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"includes": [
|
|
299
|
+
"apps/**/*.document.ts",
|
|
300
|
+
"libs/**/*.document.ts",
|
|
301
|
+
"apps/**/*.dictionary.ts",
|
|
302
|
+
"libs/**/*.dictionary.ts",
|
|
303
|
+
"apps/**/*.service.ts",
|
|
304
|
+
"libs/**/*.service.ts",
|
|
305
|
+
"apps/**/*.signal.ts",
|
|
306
|
+
"libs/**/*.signal.ts",
|
|
307
|
+
"apps/**/srvkit/**/*.ts",
|
|
308
|
+
"libs/**/srvkit/**/*.ts",
|
|
309
|
+
"apps/**/common/**/*.ts",
|
|
310
|
+
"libs/**/common/**/*.ts",
|
|
311
|
+
"apps/**/*.constant.ts",
|
|
312
|
+
"libs/**/*.constant.ts",
|
|
313
|
+
"!**/*.test.ts",
|
|
314
|
+
"!**/*.test.tsx",
|
|
315
|
+
"!**/*.spec.ts",
|
|
316
|
+
"!**/*.spec.tsx"
|
|
317
|
+
],
|
|
318
|
+
"plugins": ["./node_modules/@akanjs/devkit/lint/no-import-client-in-server.grit"]
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"includes": [
|
|
322
|
+
"apps/**/*.ts",
|
|
323
|
+
"apps/**/*.tsx",
|
|
324
|
+
"libs/**/*.ts",
|
|
325
|
+
"libs/**/*.tsx",
|
|
326
|
+
"!**/*.test.ts",
|
|
327
|
+
"!**/*.test.tsx",
|
|
328
|
+
"!**/*.spec.ts",
|
|
329
|
+
"!**/*.spec.tsx"
|
|
330
|
+
],
|
|
331
|
+
"plugins": [
|
|
332
|
+
"./node_modules/@akanjs/devkit/lint/no-raw-palette-class.grit",
|
|
333
|
+
"./node_modules/@akanjs/devkit/lint/no-arbitrary-color.grit",
|
|
334
|
+
"./node_modules/@akanjs/devkit/lint/no-daisyui-legacy-class.grit",
|
|
335
|
+
"./node_modules/@akanjs/devkit/lint/no-inline-color.grit",
|
|
336
|
+
"./node_modules/@akanjs/devkit/lint/no-interpolated-arbitrary-class.grit"
|
|
337
|
+
]
|
|
338
|
+
}
|
|
339
|
+
]
|
|
340
|
+
}
|
package/biomeBase.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** `extends` target for a workspace `biome.json`; Biome resolves it through node_modules. */
|
|
2
|
+
export const biomeBaseConfig = "@akanjs/devkit/biome.base.json";
|
|
3
|
+
|
|
4
|
+
// Biome moves rules between groups across minors — `noUnnecessaryConditions` sat in `nursery` at 2.4 and moved to
|
|
5
|
+
// `suspicious` at 2.5 — and the stale position is a hard "unknown key" error, not a warning. A workspace whose
|
|
6
|
+
// Biome disagrees with the shipped base config therefore fails to load it at all, which is why the version is
|
|
7
|
+
// pinned here instead of resolved to latest at create time. Bump this and `biome.base.json` in one commit, and run
|
|
8
|
+
// `biome migrate --write` in the workspace root and in `pkgs/@akanjs/devkit` so both configs move together.
|
|
9
|
+
export const biomeVersion = "2.5.12";
|
package/capacitorApp.test.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
clearRootCapacitorConfigs,
|
|
12
12
|
formatAndroidReleaseSigningError,
|
|
13
13
|
getAdbDeviceStateIssues,
|
|
14
|
+
getAndroidLocalServerHost,
|
|
14
15
|
getMissingAndroidReleaseSigningKeys,
|
|
15
16
|
isPlaceholderAppId,
|
|
16
17
|
materializeCapacitorConfig,
|
|
@@ -339,6 +340,13 @@ describe("Android signing diagnostics", () => {
|
|
|
339
340
|
"Android device abc123 is unauthorized. Confirm USB debugging authorization on the device.",
|
|
340
341
|
"Android device xyz is offline. Reconnect the device or restart adb.",
|
|
341
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");
|
|
342
350
|
});
|
|
343
351
|
});
|
|
344
352
|
|
package/capacitorApp.ts
CHANGED
|
@@ -24,7 +24,9 @@ interface RunIosConfig extends RunConfig {
|
|
|
24
24
|
iosDeviceId?: string;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
interface PrepareConfig extends RunConfig {
|
|
27
|
+
interface PrepareConfig extends RunConfig {
|
|
28
|
+
iosRunTargetKind?: IosRunTargetKind;
|
|
29
|
+
}
|
|
28
30
|
|
|
29
31
|
type MobileCommandEnv = Record<string, string | undefined>;
|
|
30
32
|
|
|
@@ -119,10 +121,21 @@ interface MaterializeCapacitorConfigOptions {
|
|
|
119
121
|
localServerUrl?: string;
|
|
120
122
|
localIp?: string;
|
|
121
123
|
}
|
|
124
|
+
type MobilePlatform = "ios" | "android";
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* `AppExecutor.spawn`'s own options plus the two the Capacitor config is written from before the spawn:
|
|
128
|
+
* the platform the command targets, and — for iOS — whether it targets a device or a simulator, which
|
|
129
|
+
* decide the `capacitor.config.json` that command reads.
|
|
130
|
+
*/
|
|
131
|
+
type SpawnMobileOptions = Parameters<AppExecutor["spawn"]>[2] & {
|
|
132
|
+
platform?: MobilePlatform;
|
|
133
|
+
iosRunTargetKind?: IosRunTargetKind;
|
|
134
|
+
};
|
|
122
135
|
|
|
123
136
|
export interface LocalDevHostResolution {
|
|
124
137
|
host: string;
|
|
125
|
-
source: "override" | "detected" | "loopback";
|
|
138
|
+
source: "override" | "detected" | "loopback" | "platform";
|
|
126
139
|
candidates: { name: string; address: string }[];
|
|
127
140
|
}
|
|
128
141
|
|
|
@@ -565,6 +578,16 @@ export function getAdbDeviceStateIssues(output: string) {
|
|
|
565
578
|
});
|
|
566
579
|
}
|
|
567
580
|
|
|
581
|
+
export function getAndroidLocalServerHost(adbDevicesOutput: string | undefined, fallbackHost: string) {
|
|
582
|
+
const onlineDeviceIds =
|
|
583
|
+
adbDevicesOutput
|
|
584
|
+
?.split(/\r?\n/)
|
|
585
|
+
.map((line) => line.trim().split(/\s+/))
|
|
586
|
+
.filter(([id, state]) => id && state === "device")
|
|
587
|
+
.map(([id]) => id) ?? [];
|
|
588
|
+
return onlineDeviceIds.length === 1 && onlineDeviceIds[0]?.startsWith("emulator-") ? "10.0.2.2" : fallbackHost;
|
|
589
|
+
}
|
|
590
|
+
|
|
568
591
|
export const ANDROID_MIN_SDK_VERSION = 26;
|
|
569
592
|
export function raiseGradleMinSdkVersion(content: string, floor: number = ANDROID_MIN_SDK_VERSION): string | null {
|
|
570
593
|
const match = content.match(/minSdkVersion\s*=\s*(\d+)/);
|
|
@@ -748,7 +771,7 @@ export class CapacitorApp {
|
|
|
748
771
|
async save() {
|
|
749
772
|
await this.project.commit();
|
|
750
773
|
}
|
|
751
|
-
async #prepareIos({ operation, env, regenerate = false }: PrepareConfig) {
|
|
774
|
+
async #prepareIos({ operation, env, regenerate = false, iosRunTargetKind }: PrepareConfig) {
|
|
752
775
|
await this.init({ platform: "ios", operation, env, regenerate });
|
|
753
776
|
await this.#prepareTargetAssets();
|
|
754
777
|
await this.#prepareExternalFiles("ios");
|
|
@@ -757,9 +780,10 @@ export class CapacitorApp {
|
|
|
757
780
|
await this.#applyDeepLinks("ios", { operation, env });
|
|
758
781
|
await this.#flushIosEntitlements();
|
|
759
782
|
await this.project.commit();
|
|
783
|
+
await this.#setCodeSignEntitlementsInIosIfExists("App/App.entitlements");
|
|
760
784
|
await this.#generateAssets({ operation, env });
|
|
761
785
|
this.app.verbose(`syncing iOS`);
|
|
762
|
-
await this.#spawnMobile("npx", ["cap", "sync", "ios"], { operation, env });
|
|
786
|
+
await this.#spawnMobile("npx", ["cap", "sync", "ios"], { operation, env }, { iosRunTargetKind });
|
|
763
787
|
this.app.verbose(`sync completed.`);
|
|
764
788
|
}
|
|
765
789
|
async buildIos({ env = "debug", regenerate = false }: { env?: RunConfig["env"]; regenerate?: boolean } = {}) {
|
|
@@ -777,14 +801,14 @@ export class CapacitorApp {
|
|
|
777
801
|
}
|
|
778
802
|
async runIos({ operation, env, regenerate = false, noAllowProvisioningUpdates = false, iosDeviceId }: RunIosConfig) {
|
|
779
803
|
if (operation === "release") await this.prepareWww();
|
|
780
|
-
await this.#prepareIos({ operation, env, regenerate });
|
|
781
804
|
const runTarget = await this.#selectIosRunTarget(iosDeviceId);
|
|
805
|
+
await this.#prepareIos({ operation, env, regenerate, iosRunTargetKind: runTarget.kind });
|
|
782
806
|
if (runTarget.kind === "simulator") {
|
|
783
807
|
await this.#spawnMobile(
|
|
784
808
|
"npx",
|
|
785
|
-
["cap", "run", "ios", "--target", runTarget.id],
|
|
809
|
+
["cap", "run", "ios", "--target", runTarget.id, "--no-sync"],
|
|
786
810
|
{ operation, env },
|
|
787
|
-
{ stdio: "inherit" },
|
|
811
|
+
{ stdio: "inherit", platform: "ios", iosRunTargetKind: runTarget.kind },
|
|
788
812
|
);
|
|
789
813
|
return;
|
|
790
814
|
}
|
|
@@ -878,7 +902,10 @@ export class CapacitorApp {
|
|
|
878
902
|
noAllowProvisioningUpdates: boolean;
|
|
879
903
|
}) {
|
|
880
904
|
const mobileEnv = sanitizeIosNativeRunEnv(await this.#commandEnv(operation, env));
|
|
881
|
-
const configContent = await this.#writeCapacitorConfig(
|
|
905
|
+
const configContent = await this.#writeCapacitorConfig(
|
|
906
|
+
{ operation, platform: "ios", iosRunTargetKind: runTarget.kind },
|
|
907
|
+
mobileEnv,
|
|
908
|
+
);
|
|
882
909
|
await this.#writeRootCapacitorConfig(configContent);
|
|
883
910
|
const scheme = this.#iosScheme();
|
|
884
911
|
const command = buildIosNativeRunCommand({
|
|
@@ -943,6 +970,7 @@ export class CapacitorApp {
|
|
|
943
970
|
await this.#applyAndroidMinSdkVersion();
|
|
944
971
|
await this.#applyPermissions({ operation, env });
|
|
945
972
|
await this.#applyDeepLinks("android", { operation, env });
|
|
973
|
+
await this.#disableNativeKeyboardResizeInAndroid();
|
|
946
974
|
await this.project.commit();
|
|
947
975
|
await this.#generateAssets({ operation, env });
|
|
948
976
|
await this.#ensureAndroidAssetsDir();
|
|
@@ -1010,6 +1038,24 @@ export class CapacitorApp {
|
|
|
1010
1038
|
async openAndroid() {
|
|
1011
1039
|
await this.#spawnMobile("npx", ["cap", "open", "android"], { operation: "local", env: "local" });
|
|
1012
1040
|
}
|
|
1041
|
+
async #disableNativeKeyboardResizeInAndroid() {
|
|
1042
|
+
const manifestPath = path.join(this.app.cwdPath, this.androidRootPath, "app/src/main/AndroidManifest.xml");
|
|
1043
|
+
let manifest = await readFile(manifestPath, "utf8");
|
|
1044
|
+
let changed = false;
|
|
1045
|
+
manifest = manifest.replace(/<activity\b[^>]*android:name="\.MainActivity"[^>]*>/, (activityTag) => {
|
|
1046
|
+
if (activityTag.includes("android:windowSoftInputMode=")) {
|
|
1047
|
+
const nextTag = activityTag.replace(
|
|
1048
|
+
/android:windowSoftInputMode="[^"]*"/,
|
|
1049
|
+
'android:windowSoftInputMode="adjustNothing"',
|
|
1050
|
+
);
|
|
1051
|
+
changed ||= nextTag !== activityTag;
|
|
1052
|
+
return nextTag;
|
|
1053
|
+
}
|
|
1054
|
+
changed = true;
|
|
1055
|
+
return activityTag.replace(/>$/, '\n android:windowSoftInputMode="adjustNothing">');
|
|
1056
|
+
});
|
|
1057
|
+
if (changed) await writeFile(manifestPath, manifest);
|
|
1058
|
+
}
|
|
1013
1059
|
async #ensureAndroidAssetsDir() {
|
|
1014
1060
|
await mkdir(path.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
|
|
1015
1061
|
}
|
|
@@ -1100,12 +1146,19 @@ export class CapacitorApp {
|
|
|
1100
1146
|
if (html.includes("window.__AKAN_MOBILE_TARGET__")) return html;
|
|
1101
1147
|
return html.replace(/<\/head\s*>/i, `${script}\n</head>`);
|
|
1102
1148
|
}
|
|
1103
|
-
async #writeCapacitorConfig(
|
|
1149
|
+
async #writeCapacitorConfig(
|
|
1150
|
+
{
|
|
1151
|
+
operation,
|
|
1152
|
+
platform,
|
|
1153
|
+
iosRunTargetKind,
|
|
1154
|
+
}: Pick<RunConfig, "operation"> & { platform?: MobilePlatform; iosRunTargetKind?: IosRunTargetKind },
|
|
1155
|
+
commandEnv: MobileCommandEnv,
|
|
1156
|
+
) {
|
|
1104
1157
|
await mkdir(this.targetRoot, { recursive: true });
|
|
1105
1158
|
let localIp: string | undefined;
|
|
1106
1159
|
if (operation === "local") {
|
|
1107
1160
|
const override = commandEnv.AKAN_PUBLIC_CLIENT_HOST ?? process.env.AKAN_PUBLIC_CLIENT_HOST;
|
|
1108
|
-
const resolution =
|
|
1161
|
+
const resolution = await this.#resolveLocalDevHost({ override, platform, iosRunTargetKind });
|
|
1109
1162
|
localIp = resolution.host;
|
|
1110
1163
|
this.#logDevHostResolution(resolution, commandEnv);
|
|
1111
1164
|
}
|
|
@@ -1118,11 +1171,36 @@ export class CapacitorApp {
|
|
|
1118
1171
|
await Bun.write(path.join(this.targetRoot, "capacitor.config.json"), content);
|
|
1119
1172
|
return content;
|
|
1120
1173
|
}
|
|
1174
|
+
// An explicit override always wins; an emulator/simulator run reaches the host machine through a
|
|
1175
|
+
// loopback alias (10.0.2.2 / localhost), so LAN detection only applies to physical-device runs.
|
|
1176
|
+
async #resolveLocalDevHost({
|
|
1177
|
+
override,
|
|
1178
|
+
platform,
|
|
1179
|
+
iosRunTargetKind,
|
|
1180
|
+
}: {
|
|
1181
|
+
override?: string;
|
|
1182
|
+
platform?: MobilePlatform;
|
|
1183
|
+
iosRunTargetKind?: IosRunTargetKind;
|
|
1184
|
+
}): Promise<LocalDevHostResolution> {
|
|
1185
|
+
const resolution = selectLocalDevHost(os.networkInterfaces(), { override });
|
|
1186
|
+
if (resolution.source === "override") return resolution;
|
|
1187
|
+
if (platform === "ios" && iosRunTargetKind === "simulator")
|
|
1188
|
+
return { ...resolution, host: "localhost", source: "platform" };
|
|
1189
|
+
if (platform === "android") {
|
|
1190
|
+
try {
|
|
1191
|
+
const host = getAndroidLocalServerHost(await this.#spawn("adb", ["devices"]), resolution.host);
|
|
1192
|
+
return host === resolution.host ? resolution : { ...resolution, host, source: "platform" };
|
|
1193
|
+
} catch {
|
|
1194
|
+
return resolution;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
return resolution;
|
|
1198
|
+
}
|
|
1121
1199
|
// Surface the live-reload URL a physical device must reach, and warn when auto-detection landed on
|
|
1122
1200
|
// a likely-unreachable host so a blank WebView is not mistaken for an app bug.
|
|
1123
1201
|
#logDevHostResolution(resolution: LocalDevHostResolution, commandEnv: MobileCommandEnv) {
|
|
1124
1202
|
this.app.log(`Mobile live-reload server: ${this.#localCsrUrl(resolution.host, commandEnv)}`);
|
|
1125
|
-
if (resolution.source === "override") return;
|
|
1203
|
+
if (resolution.source === "override" || resolution.source === "platform") return;
|
|
1126
1204
|
const suspicious = resolution.host === "127.0.0.1" || resolution.host.startsWith("169.254.");
|
|
1127
1205
|
const alternatives = resolution.candidates.filter((candidate) => candidate.address !== resolution.host);
|
|
1128
1206
|
if (!suspicious && alternatives.length === 0) return;
|
|
@@ -1332,20 +1410,29 @@ export class CapacitorApp {
|
|
|
1332
1410
|
command: string,
|
|
1333
1411
|
args: string[] = [],
|
|
1334
1412
|
{ operation, env }: Pick<RunConfig, "operation" | "env">,
|
|
1335
|
-
options:
|
|
1413
|
+
options: SpawnMobileOptions = {},
|
|
1336
1414
|
) {
|
|
1415
|
+
const { iosRunTargetKind, platform, ...spawnOptions } = options;
|
|
1337
1416
|
const mobileEnv = { ...(await this.#commandEnv(operation, env)), ...options.env };
|
|
1338
|
-
const configContent = await this.#writeCapacitorConfig(
|
|
1417
|
+
const configContent = await this.#writeCapacitorConfig(
|
|
1418
|
+
{ operation, platform: platform ?? this.#inferMobilePlatform(args), iosRunTargetKind },
|
|
1419
|
+
mobileEnv,
|
|
1420
|
+
);
|
|
1339
1421
|
await this.#writeRootCapacitorConfig(configContent);
|
|
1340
1422
|
try {
|
|
1341
1423
|
return await this.#spawn(command, args, {
|
|
1342
|
-
...
|
|
1424
|
+
...spawnOptions,
|
|
1343
1425
|
env: mobileEnv,
|
|
1344
1426
|
});
|
|
1345
1427
|
} finally {
|
|
1346
1428
|
await this.#clearRootCapacitorConfigs();
|
|
1347
1429
|
}
|
|
1348
1430
|
}
|
|
1431
|
+
#inferMobilePlatform(args: string[]): MobilePlatform | undefined {
|
|
1432
|
+
if (args.includes("android")) return "android";
|
|
1433
|
+
if (args.includes("ios")) return "ios";
|
|
1434
|
+
return undefined;
|
|
1435
|
+
}
|
|
1349
1436
|
async addCamera() {
|
|
1350
1437
|
await this.#setPermissionInIos({
|
|
1351
1438
|
cameraUsageDescription: "$(PRODUCT_NAME) requires access to the camera to take photos.",
|
|
@@ -1446,14 +1533,31 @@ export class CapacitorApp {
|
|
|
1446
1533
|
let end = index;
|
|
1447
1534
|
while (end < lines.length && !/^\s*\};\s*$/.test(lines[end] ?? "")) end++;
|
|
1448
1535
|
const settings = lines.slice(start, end + 1);
|
|
1449
|
-
|
|
1536
|
+
const configName = lines.slice(end + 1, end + 8).find((setting) => setting.includes("name = ")) ?? "";
|
|
1450
1537
|
const indent = line.match(/^\s*/)?.[0] ?? "";
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1538
|
+
const insertSettings = [];
|
|
1539
|
+
if (!settings.some((setting) => setting.includes("CODE_SIGN_ENTITLEMENTS"))) {
|
|
1540
|
+
insertSettings.push(`${indent}CODE_SIGN_ENTITLEMENTS = ${entitlementsRelPath};`);
|
|
1541
|
+
}
|
|
1542
|
+
if (
|
|
1543
|
+
configName.includes("name = Debug;") &&
|
|
1544
|
+
!settings.some((setting) => setting.includes("CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION"))
|
|
1545
|
+
) {
|
|
1546
|
+
insertSettings.push(`${indent}CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;`);
|
|
1547
|
+
}
|
|
1548
|
+
if (insertSettings.length > 0) {
|
|
1549
|
+
lines.splice(index, 0, ...insertSettings);
|
|
1550
|
+
index += insertSettings.length;
|
|
1551
|
+
changed = true;
|
|
1552
|
+
}
|
|
1454
1553
|
}
|
|
1455
1554
|
if (changed) await writeFile(pbxprojPath, lines.join("\n"));
|
|
1456
1555
|
}
|
|
1556
|
+
async #setCodeSignEntitlementsInIosIfExists(entitlementsRelPath: string) {
|
|
1557
|
+
const entitlementsPath = path.join(this.app.cwdPath, this.iosProjectPath, entitlementsRelPath);
|
|
1558
|
+
if (!(await Bun.file(entitlementsPath).exists())) return;
|
|
1559
|
+
await this.#setCodeSignEntitlementsInIos(entitlementsRelPath);
|
|
1560
|
+
}
|
|
1457
1561
|
async #setUrlSchemesInAndroid(schemes: string[]) {
|
|
1458
1562
|
const manifestPath = path.join(this.app.cwdPath, this.androidRootPath, "app/src/main/AndroidManifest.xml");
|
|
1459
1563
|
let manifest = await readFile(manifestPath, "utf8");
|
package/cloud/globalConfig.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdir } from "node:fs/promises";
|
|
1
|
+
import { chmod, mkdir } from "node:fs/promises";
|
|
2
2
|
import dayjs from "dayjs";
|
|
3
3
|
import { FileSys } from "../fileSys";
|
|
4
4
|
import {
|
|
@@ -29,9 +29,16 @@ export class GlobalConfig {
|
|
|
29
29
|
remoteEnvServers: akanConfig.remoteEnvServers ?? defaultAkanGlobalConfig.remoteEnvServers,
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* This file holds the cloud jwt, a refresh token that does not expire, and the LLM api key, so it is
|
|
34
|
+
* written owner-only — the same `0600` the runtime gives its control socket. `Bun.write` takes no mode
|
|
35
|
+
* and lands on `0666 & ~umask` (0644 on a default shell), so the mode is applied after the write; an
|
|
36
|
+
* existing world-readable file is tightened by the next write rather than left as it was found.
|
|
37
|
+
*/
|
|
32
38
|
static async #setAkanGlobalConfig(akanConfig: AkanGlobalConfig) {
|
|
33
|
-
await mkdir(basePath, { recursive: true });
|
|
39
|
+
await mkdir(basePath, { recursive: true, mode: 0o700 });
|
|
34
40
|
await Bun.write(configPath, JSON.stringify(akanConfig, null, 2));
|
|
41
|
+
await chmod(configPath, 0o600);
|
|
35
42
|
}
|
|
36
43
|
static async getHostConfig(host = GlobalConfig.akanCloudHost): Promise<HostConfig> {
|
|
37
44
|
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|