@akanjs/devkit 3.0.0-alpha.8 → 3.0.0-alpha.81
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/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 +65 -562
- package/akanApp/devHostPolicy.test.ts +542 -0
- package/akanApp/devHostPolicy.ts +412 -0
- package/akanApp/index.ts +2 -0
- package/akanConfig/akanConfig.test.ts +182 -14
- package/akanConfig/akanConfig.ts +132 -47
- package/akanConfig/types.ts +8 -0
- package/akanContext.ts +70 -14
- package/akanMcpContract.ts +25 -4
- package/applicationBuildRunner.test.ts +1 -1
- package/applicationBuildRunner.ts +45 -21
- 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.ts +10 -0
- package/cloud/globalConfig.ts +9 -2
- package/commandDecorators/command.ts +30 -6
- package/commandDecorators/commandBuilder.ts +20 -5
- package/commandDecorators/commandDecorators.test.ts +115 -3
- package/dependencyScanner.test.ts +99 -0
- package/dependencyScanner.ts +27 -24
- package/devkitUtils.test.ts +0 -104
- package/executors.test.ts +132 -5
- package/executors.ts +89 -14
- package/fileEditor.ts +19 -19
- package/formSetterScanner.test.ts +80 -0
- package/formSetterScanner.ts +92 -0
- package/frontendBuild/autoImportSync.test.ts +58 -0
- package/frontendBuild/autoImportSync.ts +4 -0
- 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/cssCompiler.ts +123 -12
- package/frontendBuild/cssImportResolver.ts +8 -7
- 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/routeClientBuilder.ts +12 -5
- 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/incrementalBuilder/devWatchBatch.test.ts +18 -20
- package/incrementalBuilder/devWatchBatch.ts +6 -2
- package/incrementalBuilder/incrementalBuilder.host.ts +1 -1
- package/incrementalBuilder/incrementalBuilder.proc.ts +8 -4
- package/index.ts +0 -5
- package/integration/devStabilityHarness.ts +2 -10
- package/libSource.test.ts +109 -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 +23 -10
- 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-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 -6
- package/prompter.ts +9 -4
- package/qualityScanner.test.ts +116 -0
- package/qualityScanner.ts +89 -21
- package/recipeScanner.ts +4 -1
- package/repoIdentity.ts +42 -0
- package/scanInfo.ts +32 -26
- 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/ui/ScrollList.tsx +6 -8
- package/uploadRelease.ts +2 -2
- package/workflow/executor.test.ts +146 -0
- package/workspaceLayout.test.ts +56 -4
- package/workspaceLayout.ts +49 -4
- 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/src/capacitorApp.ts
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
import type { AppExecutor } from "@akanjs/devkit/executors";
|
|
2
|
-
import { FileSys } from "@akanjs/devkit/fileSys";
|
|
3
|
-
import type { CapacitorConfig } from "@capacitor/cli";
|
|
4
|
-
import { MobileProject } from "@trapezedev/project";
|
|
5
|
-
import type { AndroidProject } from "@trapezedev/project/dist/android/project";
|
|
6
|
-
import type { IosProject } from "@trapezedev/project/dist/ios/project";
|
|
7
|
-
import { capitalize } from "akanjs/common";
|
|
8
|
-
|
|
9
|
-
import { FileEditor } from "./fileEditor";
|
|
10
|
-
|
|
11
|
-
interface RunConfig extends CapacitorConfig {
|
|
12
|
-
operation: "local" | "release";
|
|
13
|
-
version: string;
|
|
14
|
-
buildNum: number;
|
|
15
|
-
appId?: string;
|
|
16
|
-
host?: "local" | "debug" | "develop" | "main";
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export class CapacitorApp {
|
|
20
|
-
project: MobileProject & { ios: IosProject; android: AndroidProject };
|
|
21
|
-
iosTargetName = "App";
|
|
22
|
-
constructor(private readonly app: AppExecutor) {
|
|
23
|
-
this.project = new MobileProject(this.app.cwdPath, {
|
|
24
|
-
android: { path: "android" },
|
|
25
|
-
ios: { path: "ios/App" },
|
|
26
|
-
}) as MobileProject & { ios: IosProject; android: AndroidProject };
|
|
27
|
-
}
|
|
28
|
-
async init() {
|
|
29
|
-
const project = this.project as MobileProject;
|
|
30
|
-
await this.project.load();
|
|
31
|
-
const hasAndroid = await FileSys.fileExists(`${this.app.cwdPath}/android/app/build.gradle`);
|
|
32
|
-
const hasIos = await FileSys.fileExists(`${this.app.cwdPath}/ios/App/App.xcodeproj/project.pbxproj`);
|
|
33
|
-
if (!project.android && !hasAndroid) {
|
|
34
|
-
await this.app.spawn("npx", ["cap", "add", "android"]);
|
|
35
|
-
await this.project.load();
|
|
36
|
-
}
|
|
37
|
-
if (!project.ios && !hasIos) {
|
|
38
|
-
await this.app.spawn("npx", ["cap", "add", "ios"]);
|
|
39
|
-
await this.project.load();
|
|
40
|
-
}
|
|
41
|
-
return this;
|
|
42
|
-
}
|
|
43
|
-
async save() {
|
|
44
|
-
await this.project.commit();
|
|
45
|
-
}
|
|
46
|
-
async #prepareIos() {
|
|
47
|
-
const isAdded = await FileSys.fileExists(`${this.app.cwdPath}/ios/App/App.xcodeproj/project.pbxproj`);
|
|
48
|
-
if (!isAdded) {
|
|
49
|
-
await this.app.spawn("npx", ["cap", "add", "ios"]);
|
|
50
|
-
await this.app.spawn("npx", ["@capacitor/assets", "generate"]);
|
|
51
|
-
} else this.app.verbose(`iOS already added, skip adding process`);
|
|
52
|
-
this.app.verbose(`syncing iOS`);
|
|
53
|
-
await this.app.spawn("npx", ["cap", "sync", "ios"]);
|
|
54
|
-
this.app.verbose(`sync completed.`);
|
|
55
|
-
}
|
|
56
|
-
async buildIos() {
|
|
57
|
-
await this.#prepareIos();
|
|
58
|
-
this.app.verbose(`build completed iOS.`);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
async syncIos() {
|
|
62
|
-
await this.app.spawn("npx", ["cap", "sync", "ios"]);
|
|
63
|
-
}
|
|
64
|
-
async openIos() {
|
|
65
|
-
await this.app.spawn("npx", ["cap", "open", "ios"]);
|
|
66
|
-
}
|
|
67
|
-
async runIos({ operation, appId, version = "0.0.1", buildNum = 1, host = "local" }: RunConfig) {
|
|
68
|
-
const defaultAppId = `com.${this.app.name}.app`;
|
|
69
|
-
await this.#prepareIos();
|
|
70
|
-
this.project.ios.setBundleId("App", "Debug", appId ?? defaultAppId);
|
|
71
|
-
this.project.ios.setBundleId("App", "Release", appId ?? defaultAppId);
|
|
72
|
-
await this.project.ios.setVersion("App", "Debug", version);
|
|
73
|
-
await this.project.ios.setVersion("App", "Release", version);
|
|
74
|
-
await this.project.ios.setBuild("App", "Debug", buildNum);
|
|
75
|
-
await this.project.ios.setBuild("App", "Release", buildNum);
|
|
76
|
-
await this.project.commit();
|
|
77
|
-
await this.app.spawn(
|
|
78
|
-
"npx",
|
|
79
|
-
["cross-env", `APP_OPERATION_MODE=${operation}`, `BUN_PUBLIC_ENV=${host}`, "npx", "cap", "run", "ios"],
|
|
80
|
-
{
|
|
81
|
-
stdio: "inherit",
|
|
82
|
-
},
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
// this.project.ios.incrementBuild("App", "Debug");
|
|
86
|
-
// this.project.ios.incrementBuild("App", "Release");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async #prepareAndroid() {
|
|
90
|
-
const isAdded = await Bun.file(`${this.app.cwdPath}/android/app/build.gradle`).exists();
|
|
91
|
-
if (!isAdded) {
|
|
92
|
-
await this.app.spawn("npx", ["cap", "add", "android"]);
|
|
93
|
-
} else this.app.verbose(`Android already added, skip adding process`);
|
|
94
|
-
await this.app.spawn("npx", ["@capacitor/assets", "generate"]);
|
|
95
|
-
await this.app.spawn("npx", ["cap", "sync", "android"]);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async #updateAndroidBuildTypes() {
|
|
99
|
-
//keystore 기본 설정 및 debug, release 설정
|
|
100
|
-
|
|
101
|
-
const appGradle = await FileEditor.create(`${this.app.cwdPath}/android/app/build.gradle`);
|
|
102
|
-
const buildTypesBlock = `
|
|
103
|
-
debug {
|
|
104
|
-
applicationIdSuffix ".debug"
|
|
105
|
-
versionNameSuffix "-DEBUG"
|
|
106
|
-
debuggable true
|
|
107
|
-
minifyEnabled false
|
|
108
|
-
}
|
|
109
|
-
`;
|
|
110
|
-
const singinConfigBlock = `
|
|
111
|
-
signingConfigs {
|
|
112
|
-
debug {
|
|
113
|
-
storeFile file('debug.keystore')
|
|
114
|
-
storePassword 'android'
|
|
115
|
-
keyAlias 'androiddebugkey'
|
|
116
|
-
keyPassword 'android'
|
|
117
|
-
}
|
|
118
|
-
release {
|
|
119
|
-
if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
|
|
120
|
-
storeFile file(MYAPP_RELEASE_STORE_FILE)
|
|
121
|
-
storePassword MYAPP_RELEASE_STORE_PASSWORD
|
|
122
|
-
keyAlias MYAPP_RELEASE_KEY_ALIAS
|
|
123
|
-
keyPassword MYAPP_RELEASE_KEY_PASSWORD
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
`;
|
|
128
|
-
if (appGradle.find("signingConfigs {") === -1) {
|
|
129
|
-
appGradle.insertBefore("buildTypes {", singinConfigBlock);
|
|
130
|
-
}
|
|
131
|
-
if (appGradle.find(`applicationIdSuffix ".debug"`) === -1) {
|
|
132
|
-
appGradle.insertAfter("buildTypes {", buildTypesBlock);
|
|
133
|
-
}
|
|
134
|
-
await appGradle.save();
|
|
135
|
-
}
|
|
136
|
-
async buildAndroid(assembleType: "apk" | "aab") {
|
|
137
|
-
await this.#prepareAndroid();
|
|
138
|
-
await this.#updateAndroidBuildTypes();
|
|
139
|
-
//윈도우는 gradlew.bat 사용
|
|
140
|
-
const isWindows = process.platform === "win32";
|
|
141
|
-
const gradleCommand = isWindows ? "gradlew.bat" : "./gradlew";
|
|
142
|
-
|
|
143
|
-
await this.app.spawn(gradleCommand, [assembleType === "apk" ? "assembleRelease" : "bundleRelease"], {
|
|
144
|
-
stdio: "inherit",
|
|
145
|
-
cwd: `${this.app.cwdPath}/android`,
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
async openAndroid() {
|
|
149
|
-
await this.app.spawn("npx", ["cap", "open", "android"]);
|
|
150
|
-
}
|
|
151
|
-
async syncAndroid() {
|
|
152
|
-
await this.#prepareAndroid();
|
|
153
|
-
this.app.log(`Sync Android Completed.`);
|
|
154
|
-
}
|
|
155
|
-
async runAndroid({ operation, appName, appId, version = "0.0.1", buildNum = 1, host = "local" }: RunConfig) {
|
|
156
|
-
const defaultAppId = `com.${this.app.name}.app`;
|
|
157
|
-
const defaultAppName = this.app.name;
|
|
158
|
-
await this.project.android.setVersionName(version);
|
|
159
|
-
await this.project.android.setPackageName(appId ?? defaultAppId);
|
|
160
|
-
await this.project.android.setVersionCode(buildNum);
|
|
161
|
-
const versionName = await this.project.android.getVersionName();
|
|
162
|
-
const versionCode = await this.project.android.getVersionCode();
|
|
163
|
-
await this.project.android.setAppName(appName ?? defaultAppName);
|
|
164
|
-
await this.project.commit();
|
|
165
|
-
await this.#prepareAndroid();
|
|
166
|
-
|
|
167
|
-
this.app.logger.info(`Running Android in ${operation} mode on ${host} host`);
|
|
168
|
-
await this.app.spawn(
|
|
169
|
-
"npx",
|
|
170
|
-
["cross-env", `BUN_PUBLIC_ENV=${host}`, `APP_OPERATION_MODE=${operation}`, "npx", "cap", "run", "android"],
|
|
171
|
-
{
|
|
172
|
-
stdio: "inherit",
|
|
173
|
-
},
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
//? 릴리즈시 buildNum +1 version 파라미터 받아서 업데이트
|
|
178
|
-
async updateAndroidVersion(version: string, buildNum: number) {
|
|
179
|
-
//TODO: 테스트 확인 필요
|
|
180
|
-
await this.project.android.setVersionName(version);
|
|
181
|
-
await this.project.android.setVersionCode(buildNum);
|
|
182
|
-
const versionName = await this.project.android.getVersionName();
|
|
183
|
-
const versionCode = await this.project.android.getVersionCode();
|
|
184
|
-
await this.project.commit();
|
|
185
|
-
}
|
|
186
|
-
async releaseIos() {
|
|
187
|
-
//TODO: 작업 필요
|
|
188
|
-
const isAdded = await Bun.file(`${this.app.cwdPath}/ios/App/App.xcodeproj/project.pbxproj`).exists();
|
|
189
|
-
if (!isAdded) {
|
|
190
|
-
await this.app.spawn("npx cap add ios");
|
|
191
|
-
await this.app.spawn("npx @capacitor/assets generate");
|
|
192
|
-
} else this.app.log(`iOS already added, skip adding process`);
|
|
193
|
-
await this.app.spawn("cross-env", ["APP_OPERATION_MODE=release", "npx", "cap", "sync", "ios"]);
|
|
194
|
-
}
|
|
195
|
-
async releaseAndroid() {
|
|
196
|
-
//TODO: 작업 필요
|
|
197
|
-
const isAdded = await Bun.file(`${this.app.cwdPath}/android/app/build.gradle`).exists();
|
|
198
|
-
if (!isAdded) {
|
|
199
|
-
await this.app.spawn("npx cap add android");
|
|
200
|
-
await this.app.spawn("npx @capacitor/assets generate");
|
|
201
|
-
} else this.app.log(`android already added, skip adding process`);
|
|
202
|
-
await this.app.spawn("cross-env", ["APP_OPERATION_MODE=release", "npx", "cap", "sync", "android"]);
|
|
203
|
-
}
|
|
204
|
-
async addCamera() {
|
|
205
|
-
await this.#setPermissionInIos({
|
|
206
|
-
cameraUsageDescription: "$(PRODUCT_NAME) requires access to the camera to take photos.",
|
|
207
|
-
photoAddUsageDescription: "$(PRODUCT_NAME) requires access to the photo library to take photos.",
|
|
208
|
-
photoUsageDescription: "$(PRODUCT_NAME) requires access to the photo library to take photos.",
|
|
209
|
-
});
|
|
210
|
-
this.#setPermissionsInAndroid(["READ_MEDIA_IMAGES", "READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE"]);
|
|
211
|
-
}
|
|
212
|
-
async addContact() {
|
|
213
|
-
await this.#setPermissionInIos({
|
|
214
|
-
contactsUsageDescription: "$(PRODUCT_NAME) requires access to the contacts to add new contacts.",
|
|
215
|
-
});
|
|
216
|
-
this.#setPermissionsInAndroid(["READ_CONTACTS", "WRITE_CONTACTS"]);
|
|
217
|
-
}
|
|
218
|
-
async addLocation() {
|
|
219
|
-
await this.#setPermissionInIos({
|
|
220
|
-
locationAlwaysUsageDescription: "$(PRODUCT_NAME) requires access to the location to get the user's location.",
|
|
221
|
-
locationWhenInUseUsageDescription: "$(PRODUCT_NAME) requires access to the location to get the user's location.",
|
|
222
|
-
});
|
|
223
|
-
this.#setPermissionsInAndroid(["ACCESS_COARSE_LOCATION", "ACCESS_FINE_LOCATION"]);
|
|
224
|
-
this.#setFeaturesInAndroid(["android.hardware.location.gps"]);
|
|
225
|
-
}
|
|
226
|
-
async #setPermissionInIos(permissions: { [key: string]: string }) {
|
|
227
|
-
const updateNs = Object.fromEntries(
|
|
228
|
-
Object.entries(permissions).map(([key, value]) => [`NS${capitalize(key)}`, value]),
|
|
229
|
-
);
|
|
230
|
-
await Promise.all([
|
|
231
|
-
this.project.ios.updateInfoPlist(this.iosTargetName, "Debug", updateNs),
|
|
232
|
-
this.project.ios.updateInfoPlist(this.iosTargetName, "Release", updateNs),
|
|
233
|
-
]);
|
|
234
|
-
}
|
|
235
|
-
#setFeaturesInAndroid(features: string[]) {
|
|
236
|
-
for (const feature of features) {
|
|
237
|
-
if (this.#hasFeatureInAndroid(feature)) {
|
|
238
|
-
this.app.logger.info(`${feature} already exists in android`);
|
|
239
|
-
return this;
|
|
240
|
-
}
|
|
241
|
-
this.app.logger.info(`Adding ${feature} to android`);
|
|
242
|
-
this.project.android
|
|
243
|
-
.getAndroidManifest()
|
|
244
|
-
.injectFragment("manifest", `<uses-feature android:name="${feature}" />`);
|
|
245
|
-
}
|
|
246
|
-
return this;
|
|
247
|
-
}
|
|
248
|
-
#getFeaturesInAndroid() {
|
|
249
|
-
const androidManifest = this.project.android.getAndroidManifest();
|
|
250
|
-
const element = androidManifest.getDocumentElement();
|
|
251
|
-
if (!element) throw new Error("manifest not found");
|
|
252
|
-
const usesFeature = element.getElementsByTagName("uses-feature");
|
|
253
|
-
return Array.from(usesFeature).map((feature) => feature.getAttribute("android:name"));
|
|
254
|
-
}
|
|
255
|
-
#hasFeatureInAndroid(feature: string) {
|
|
256
|
-
return this.#getFeaturesInAndroid().includes(feature);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
#setPermissionsInAndroid(permissions: string[]) {
|
|
260
|
-
for (const permission of permissions) {
|
|
261
|
-
if (this.#hasPermissionInAndroid(permission)) {
|
|
262
|
-
this.app.logger.info(`${permission} already exists in android`);
|
|
263
|
-
return this;
|
|
264
|
-
}
|
|
265
|
-
this.app.logger.info(`Adding ${permission} to android`);
|
|
266
|
-
this.project.android
|
|
267
|
-
.getAndroidManifest()
|
|
268
|
-
.injectFragment("manifest", `<uses-permission android:name="android.permission.${permission}" />`);
|
|
269
|
-
}
|
|
270
|
-
return this;
|
|
271
|
-
}
|
|
272
|
-
#getPermissionsInAndroid() {
|
|
273
|
-
const androidManifest = this.project.android.getAndroidManifest();
|
|
274
|
-
const element = androidManifest.getDocumentElement();
|
|
275
|
-
if (!element) throw new Error("manifest not found");
|
|
276
|
-
const usesPermission = element.getElementsByTagName("uses-permission");
|
|
277
|
-
return Array.from(usesPermission).map((permission) => permission.getAttribute("android:name"));
|
|
278
|
-
}
|
|
279
|
-
#hasPermissionInAndroid(permission: string) {
|
|
280
|
-
return this.#getPermissionsInAndroid().includes(permission);
|
|
281
|
-
}
|
|
282
|
-
}
|
package/streamAi.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { PromptTemplate } from "@langchain/core/prompts";
|
|
2
|
-
import { RunnableSequence } from "@langchain/core/runnables";
|
|
3
|
-
import { ChatOpenAI } from "@langchain/openai";
|
|
4
|
-
|
|
5
|
-
interface StreamResponse {
|
|
6
|
-
content: string;
|
|
7
|
-
chunk?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const streamAi = async (
|
|
11
|
-
question: string,
|
|
12
|
-
callback: (chunk: string) => void = (chunk) => {
|
|
13
|
-
process.stdout.write(chunk);
|
|
14
|
-
},
|
|
15
|
-
): Promise<StreamResponse> => {
|
|
16
|
-
const createStreamingModel = (apiKey = process.env.DEEPSEEK_API_KEY) => {
|
|
17
|
-
if (!apiKey) throw new Error(`process.env.DEEPSEEK_API_KEY is not set`);
|
|
18
|
-
return new ChatOpenAI({
|
|
19
|
-
modelName: "deepseek-reasoner",
|
|
20
|
-
temperature: 0.7,
|
|
21
|
-
streaming: true, // Enable streaming
|
|
22
|
-
configuration: { baseURL: "https://api.deepseek.com/v1", apiKey },
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
const createProcessingChain = () => {
|
|
26
|
-
return RunnableSequence.from([PromptTemplate.fromTemplate(`Answer concisely: {question}`), createStreamingModel()]);
|
|
27
|
-
};
|
|
28
|
-
try {
|
|
29
|
-
const chain = createProcessingChain();
|
|
30
|
-
const stream = await chain.stream({ question });
|
|
31
|
-
|
|
32
|
-
let fullResponse = "";
|
|
33
|
-
for await (const chunk of stream) {
|
|
34
|
-
const content = chunk.content;
|
|
35
|
-
if (typeof content === "string") {
|
|
36
|
-
fullResponse += content;
|
|
37
|
-
callback(content); // Send individual chunks to callback
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return { content: fullResponse };
|
|
42
|
-
} catch (error) {
|
|
43
|
-
throw new Error("Failed to stream response");
|
|
44
|
-
}
|
|
45
|
-
};
|