mimi-seed 0.19.9 → 0.19.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/{chunk-I3C5DIUA.js → chunk-2FKWHED2.js} +1 -1
- package/dist/{chunk-ZGMPOJRY.js → chunk-TQHLWSFR.js} +4 -2
- package/dist/{chunk-KY6LI3CK.js → chunk-UKNCSE4V.js} +81 -4
- package/dist/index.js +1047 -50
- package/dist/{mcp-client-DZNDKAGQ.js → mcp-client-L5BQ5VG4.js} +2 -2
- package/dist/{setup-RI2NDOZR.js → setup-VO5WN32U.js} +2 -2
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -11,7 +11,8 @@ npx mimi-seed check --local
|
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
로그인 없이 현재 저장소의 앱 식별자, Android Target API, Google Play Billing 지원 상태를 먼저 검사합니다.
|
|
14
|
-
|
|
14
|
+
검사기는 CLI에 번들되어 전체 MCP 패키지를 추가 설치하지 않으며, 저장소 전용 모드에서는 네트워크도 호출하지
|
|
15
|
+
않습니다. 정책 결과에는 근거 파일과 공식 출처가 포함됩니다. 실제 스토어 상태까지 연결하려면 그다음 실행합니다.
|
|
15
16
|
|
|
16
17
|
```bash
|
|
17
18
|
npx mimi-seed init
|
|
@@ -118,6 +118,7 @@ var ko = {
|
|
|
118
118
|
serverOk: "Mimi Seed \uC11C\uBC84 \uC5F0\uACB0\uB428",
|
|
119
119
|
appCount: (n) => `\uC571 ${n}\uAC1C`,
|
|
120
120
|
unknownService: (id) => `${id} (\uC54C \uC218 \uC5C6\uB294 \uC11C\uBE44\uC2A4)`,
|
|
121
|
+
credentialMismatch: (field, expected, actual) => `${field} \uBD88\uC77C\uCE58 \u2014 \uC694\uAD6C\uAC12 ${expected}, \uD604\uC7AC\uAC12 ${actual ?? "\uC5C6\uC74C"}`,
|
|
121
122
|
credsHint: " \uC804\uBD80 \uC5F0\uACB0\uD558\uAE30: mimi-seed setup \xB7 OAuth \uC2E0\uC120\uB3C4: mimi-seed auth status\n",
|
|
122
123
|
nodeTooOld: (v) => `${v} \u2014 v20 \uC774\uC0C1 \uD544\uC694 (.nvmrc \uCC38\uACE0)`,
|
|
123
124
|
gitRepo: "Git \uC800\uC7A5\uC18C",
|
|
@@ -126,7 +127,7 @@ var ko = {
|
|
|
126
127
|
noGit: "Git \uC800\uC7A5\uC18C \uC5C6\uC74C",
|
|
127
128
|
noGitDetail: "mimi-seed notes \uC0AC\uC6A9 \uBD88\uAC00",
|
|
128
129
|
noApp: "\uC571 \uAC10\uC9C0 \uC5C6\uC74C",
|
|
129
|
-
noAppDetail: "
|
|
130
|
+
noAppDetail: "Expo / Gradle / Xcode / Unity \uC571 \uC124\uC815 \uC5C6\uC74C",
|
|
130
131
|
unnamed: "(\uC774\uB984 \uBBF8\uC0C1)",
|
|
131
132
|
requirements: (proj) => `${proj} \uC694\uAD6C\uC0AC\uD56D (.mimi-seed.json)`,
|
|
132
133
|
thisProject: "\uC774 \uD504\uB85C\uC81D\uD2B8"
|
|
@@ -220,6 +221,7 @@ MIMI_SEED_LANG takes precedence when set.`,
|
|
|
220
221
|
serverOk: "Connected to Mimi Seed",
|
|
221
222
|
appCount: (n) => `${n} app(s)`,
|
|
222
223
|
unknownService: (id) => `${id} (unknown service)`,
|
|
224
|
+
credentialMismatch: (field, expected, actual) => `${field} mismatch \u2014 expected ${expected}, current ${actual ?? "missing"}`,
|
|
223
225
|
credsHint: " Connect everything: mimi-seed setup \xB7 OAuth freshness: mimi-seed auth status\n",
|
|
224
226
|
nodeTooOld: (v) => `${v} \u2014 v20+ required (see .nvmrc)`,
|
|
225
227
|
gitRepo: "Git repository",
|
|
@@ -228,7 +230,7 @@ MIMI_SEED_LANG takes precedence when set.`,
|
|
|
228
230
|
noGit: "Not a git repository",
|
|
229
231
|
noGitDetail: "mimi-seed notes is unavailable",
|
|
230
232
|
noApp: "No app detected",
|
|
231
|
-
noAppDetail: "no
|
|
233
|
+
noAppDetail: "no Expo / Gradle / Xcode / Unity app configuration",
|
|
232
234
|
unnamed: "(unnamed)",
|
|
233
235
|
requirements: (proj) => `${proj} requirements (.mimi-seed.json)`,
|
|
234
236
|
thisProject: "This project"
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
resolveLang,
|
|
6
6
|
t,
|
|
7
7
|
writeSettings
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-TQHLWSFR.js";
|
|
9
9
|
|
|
10
10
|
// src/setup.ts
|
|
11
11
|
import kleur2 from "kleur";
|
|
@@ -242,7 +242,14 @@ var CREDENTIALS = [
|
|
|
242
242
|
docsAnchor: "app-store-connect",
|
|
243
243
|
detect: (home) => {
|
|
244
244
|
const cfg = readJson(home, "appstore.json");
|
|
245
|
-
return cfg ? {
|
|
245
|
+
return cfg ? {
|
|
246
|
+
present: true,
|
|
247
|
+
detail: cfg.keyId ? `keyId ${cfg.keyId}` : void 0,
|
|
248
|
+
identity: Object.fromEntries([
|
|
249
|
+
["keyId", cfg.keyId],
|
|
250
|
+
["issuerId", cfg.issuerId]
|
|
251
|
+
].filter((entry) => typeof entry[1] === "string"))
|
|
252
|
+
} : { present: false };
|
|
246
253
|
}
|
|
247
254
|
},
|
|
248
255
|
{
|
|
@@ -769,6 +776,37 @@ async function pathExists(p) {
|
|
|
769
776
|
return false;
|
|
770
777
|
}
|
|
771
778
|
}
|
|
779
|
+
async function importedJsonObjects(configPath, text, root) {
|
|
780
|
+
const result = /* @__PURE__ */ new Map();
|
|
781
|
+
const imports = [
|
|
782
|
+
...text.matchAll(/\bimport\s+([A-Za-z_$][\w$]*)\s+from\s+["']([^"']+\.json)["']/g),
|
|
783
|
+
...text.matchAll(/\bconst\s+([A-Za-z_$][\w$]*)\s*=\s*require\(\s*["']([^"']+\.json)["']\s*\)/g)
|
|
784
|
+
];
|
|
785
|
+
for (const match of imports) {
|
|
786
|
+
if (!match[2].startsWith(".")) continue;
|
|
787
|
+
const candidate = path5.resolve(path5.dirname(configPath), match[2]);
|
|
788
|
+
const relative = path5.relative(root, candidate);
|
|
789
|
+
if (relative.startsWith(`..${path5.sep}`) || relative === ".." || path5.isAbsolute(relative)) continue;
|
|
790
|
+
const jsonText = await readIfExists(candidate);
|
|
791
|
+
if (!jsonText) continue;
|
|
792
|
+
try {
|
|
793
|
+
const json = JSON.parse(jsonText);
|
|
794
|
+
if (json && typeof json === "object" && !Array.isArray(json)) {
|
|
795
|
+
result.set(match[1], json);
|
|
796
|
+
}
|
|
797
|
+
} catch {
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return result;
|
|
801
|
+
}
|
|
802
|
+
function importedMember(text, block, field, imports) {
|
|
803
|
+
const match = new RegExp(
|
|
804
|
+
`\\b${block}\\s*:\\s*\\{[\\s\\S]{0,5000}?\\b${field}\\s*:\\s*([A-Za-z_$][\\w$]*)\\.([A-Za-z_$][\\w$]*)`
|
|
805
|
+
).exec(text);
|
|
806
|
+
if (!match) return void 0;
|
|
807
|
+
const value = imports.get(match[1])?.[match[2]];
|
|
808
|
+
return typeof value === "string" ? value : void 0;
|
|
809
|
+
}
|
|
772
810
|
async function walk(root, match, maxDepth = 5) {
|
|
773
811
|
const found = [];
|
|
774
812
|
const skipDirs = /* @__PURE__ */ new Set([
|
|
@@ -823,6 +861,17 @@ async function detectHints(cwd) {
|
|
|
823
861
|
} catch {
|
|
824
862
|
}
|
|
825
863
|
}
|
|
864
|
+
for (const fname of ["app.config.js", "app.config.cjs", "app.config.mjs", "app.config.ts"]) {
|
|
865
|
+
const configPath = path5.join(cwd, fname);
|
|
866
|
+
const txt = await readIfExists(configPath);
|
|
867
|
+
if (!txt) continue;
|
|
868
|
+
const imports = await importedJsonObjects(configPath, txt, cwd);
|
|
869
|
+
const pkg = txt.match(/\bandroid\s*:\s*\{[\s\S]{0,5000}?\bpackage\s*:\s*["']([^"']+)["']/)?.[1] ?? importedMember(txt, "android", "package", imports);
|
|
870
|
+
const bid = txt.match(/\bios\s*:\s*\{[\s\S]{0,5000}?\bbundleIdentifier\s*:\s*["']([^"']+)["']/)?.[1] ?? importedMember(txt, "ios", "bundleIdentifier", imports);
|
|
871
|
+
if (pkg || bid) {
|
|
872
|
+
hints.push({ packageName: pkg, bundleId: bid, source: [fname] });
|
|
873
|
+
}
|
|
874
|
+
}
|
|
826
875
|
const gradleFiles = await walk(
|
|
827
876
|
cwd,
|
|
828
877
|
(n) => n === "build.gradle" || n === "build.gradle.kts",
|
|
@@ -867,6 +916,34 @@ async function detectHints(cwd) {
|
|
|
867
916
|
}
|
|
868
917
|
}
|
|
869
918
|
}
|
|
919
|
+
const unitySettings = path5.join(cwd, "ProjectSettings", "ProjectSettings.asset");
|
|
920
|
+
const unityText = await readIfExists(unitySettings);
|
|
921
|
+
if (unityText) {
|
|
922
|
+
const lines = unityText.split(/\r?\n/);
|
|
923
|
+
const identifierStart = lines.findIndex((line) => /^\s*applicationIdentifier:\s*$/.test(line));
|
|
924
|
+
const baseIndent = identifierStart >= 0 ? lines[identifierStart].match(/^\s*/)?.[0].length ?? 0 : 0;
|
|
925
|
+
let packageName;
|
|
926
|
+
let bundleId;
|
|
927
|
+
if (identifierStart >= 0) {
|
|
928
|
+
for (const line of lines.slice(identifierStart + 1)) {
|
|
929
|
+
if (!line.trim()) continue;
|
|
930
|
+
const indent = line.match(/^\s*/)?.[0].length ?? 0;
|
|
931
|
+
if (indent <= baseIndent) break;
|
|
932
|
+
const entry = line.match(/^\s+(Android|iPhone|iOS):\s*([^\s#]+)\s*$/);
|
|
933
|
+
if (entry?.[1] === "Android") packageName = entry[2];
|
|
934
|
+
if (entry && entry[1] !== "Android") bundleId = entry[2];
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
const name = unityText.match(/^\s*productName:\s*(.+?)\s*$/m)?.[1];
|
|
938
|
+
if (packageName || bundleId) {
|
|
939
|
+
hints.push({
|
|
940
|
+
name,
|
|
941
|
+
packageName,
|
|
942
|
+
bundleId,
|
|
943
|
+
source: [path5.relative(cwd, unitySettings)]
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
}
|
|
870
947
|
const pkgJson = await readIfExists(path5.join(cwd, "package.json"));
|
|
871
948
|
if (pkgJson) {
|
|
872
949
|
try {
|
|
@@ -903,7 +980,7 @@ async function detectHints(cwd) {
|
|
|
903
980
|
return merged.filter((h) => h.packageName || h.bundleId);
|
|
904
981
|
}
|
|
905
982
|
async function hasAnyProjectSignal(cwd) {
|
|
906
|
-
return await pathExists(path5.join(cwd, "package.json")) || await pathExists(path5.join(cwd, "app.json")) || await pathExists(path5.join(cwd, "android")) || await pathExists(path5.join(cwd, "ios"));
|
|
983
|
+
return await pathExists(path5.join(cwd, "package.json")) || await pathExists(path5.join(cwd, "app.json")) || await pathExists(path5.join(cwd, "android")) || await pathExists(path5.join(cwd, "ios")) || await pathExists(path5.join(cwd, "ProjectSettings", "ProjectSettings.asset"));
|
|
907
984
|
}
|
|
908
985
|
|
|
909
986
|
// src/deploy.ts
|
|
@@ -1595,7 +1672,7 @@ async function cmdDeploy(argv) {
|
|
|
1595
1672
|
}
|
|
1596
1673
|
let appId = args.appId;
|
|
1597
1674
|
if (!appId) {
|
|
1598
|
-
const { mcpCall } = await import("./mcp-client-
|
|
1675
|
+
const { mcpCall } = await import("./mcp-client-L5BQ5VG4.js");
|
|
1599
1676
|
const r = await mcpCall(cfg.endpoint, cfg.token, "list_apps", {});
|
|
1600
1677
|
if (!r.isError) {
|
|
1601
1678
|
try {
|