teamix-evo 0.15.6 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/core/index.d.ts +43 -3
- package/dist/core/index.js +567 -57
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +486 -253
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/core/index.js
CHANGED
|
@@ -461,9 +461,9 @@ async function installSkills(options) {
|
|
|
461
461
|
async function renderSkillFiles(skill, options) {
|
|
462
462
|
const { data, packageRoot } = options;
|
|
463
463
|
const sourceAbs = path7.resolve(packageRoot, skill.source);
|
|
464
|
-
const
|
|
464
|
+
const stat4 = await fs6.stat(sourceAbs);
|
|
465
465
|
const rendered = /* @__PURE__ */ new Map();
|
|
466
|
-
if (
|
|
466
|
+
if (stat4.isFile()) {
|
|
467
467
|
const content = await renderSkillContent(sourceAbs, skill, data);
|
|
468
468
|
rendered.set("SKILL.md", content);
|
|
469
469
|
return rendered;
|
|
@@ -726,13 +726,13 @@ async function pruneEmptyIdeSkillDirs(args) {
|
|
|
726
726
|
}
|
|
727
727
|
for (const name of entries) {
|
|
728
728
|
const dir = path7.join(skillsRoot, name);
|
|
729
|
-
let
|
|
729
|
+
let stat4;
|
|
730
730
|
try {
|
|
731
|
-
|
|
731
|
+
stat4 = await fs6.stat(dir);
|
|
732
732
|
} catch {
|
|
733
733
|
continue;
|
|
734
734
|
}
|
|
735
|
-
if (!
|
|
735
|
+
if (!stat4.isDirectory()) continue;
|
|
736
736
|
let children;
|
|
737
737
|
try {
|
|
738
738
|
children = await fs6.readdir(dir);
|
|
@@ -2789,13 +2789,44 @@ async function detectProjectState2(cwd) {
|
|
|
2789
2789
|
significantEntries: []
|
|
2790
2790
|
};
|
|
2791
2791
|
}
|
|
2792
|
+
let legacyLib = "unknown";
|
|
2793
|
+
let buildTool = "unknown";
|
|
2794
|
+
let allDeps = {};
|
|
2795
|
+
if (hasPackageJson) {
|
|
2796
|
+
const pkgRaw = await readFileOrNull(path15.join(absCwd, "package.json"));
|
|
2797
|
+
if (pkgRaw) {
|
|
2798
|
+
try {
|
|
2799
|
+
const pkg = JSON.parse(pkgRaw);
|
|
2800
|
+
allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
2801
|
+
} catch {
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
if ("@alifd/next" in allDeps || "@ali/teamix-material" in allDeps) {
|
|
2806
|
+
legacyLib = "fusion";
|
|
2807
|
+
} else if ("antd" in allDeps) {
|
|
2808
|
+
legacyLib = "antd";
|
|
2809
|
+
} else if ("element-ui" in allDeps || "element-plus" in allDeps) {
|
|
2810
|
+
legacyLib = "element";
|
|
2811
|
+
}
|
|
2812
|
+
if (await fileExists(path15.join(absCwd, "build.json"))) {
|
|
2813
|
+
buildTool = "ice";
|
|
2814
|
+
} else if (await fileExists(path15.join(absCwd, "vite.config.ts")) || await fileExists(path15.join(absCwd, "vite.config.js")) || await fileExists(path15.join(absCwd, "vite.config.mts"))) {
|
|
2815
|
+
buildTool = "vite";
|
|
2816
|
+
} else if (await fileExists(path15.join(absCwd, "webpack.config.js")) || await fileExists(path15.join(absCwd, "webpack.config.ts"))) {
|
|
2817
|
+
buildTool = "webpack";
|
|
2818
|
+
} else if ("umi" in allDeps || "@umijs/max" in allDeps) {
|
|
2819
|
+
buildTool = "umi";
|
|
2820
|
+
}
|
|
2792
2821
|
return {
|
|
2793
2822
|
state: "other",
|
|
2794
2823
|
cwd: absCwd,
|
|
2795
2824
|
hasTeamixDir: false,
|
|
2796
2825
|
hasPackageJson,
|
|
2797
2826
|
hasComponentsJson,
|
|
2798
|
-
significantEntries: significant.slice(0, 20).sort()
|
|
2827
|
+
significantEntries: significant.slice(0, 20).sort(),
|
|
2828
|
+
legacyLib,
|
|
2829
|
+
buildTool
|
|
2799
2830
|
};
|
|
2800
2831
|
}
|
|
2801
2832
|
|
|
@@ -2803,7 +2834,8 @@ async function detectProjectState2(cwd) {
|
|
|
2803
2834
|
var COMMAND_LABELS = {
|
|
2804
2835
|
init: "\u521D\u59CB\u5316 Teamix Evo \u5957\u4EF6",
|
|
2805
2836
|
migrate: "shadcn \u9879\u76EE\u8FC1\u79FB\u4E3A Teamix Evo \u5957\u4EF6",
|
|
2806
|
-
update: "Teamix Evo \u5957\u4EF6\u66F4\u65B0"
|
|
2837
|
+
update: "Teamix Evo \u5957\u4EF6\u66F4\u65B0",
|
|
2838
|
+
graft: "\u53E0\u52A0 Teamix Evo \u80FD\u529B"
|
|
2807
2839
|
};
|
|
2808
2840
|
var STATE_LABELS = {
|
|
2809
2841
|
empty: "\u7A7A\u76EE\u5F55",
|
|
@@ -2814,13 +2846,14 @@ var STATE_LABELS = {
|
|
|
2814
2846
|
var VALID_STATES = {
|
|
2815
2847
|
init: "empty",
|
|
2816
2848
|
migrate: "shadcn",
|
|
2817
|
-
update: "teamix-evo"
|
|
2849
|
+
update: "teamix-evo",
|
|
2850
|
+
graft: "other"
|
|
2818
2851
|
};
|
|
2819
2852
|
var STATE_TO_COMMAND = {
|
|
2820
2853
|
empty: "init",
|
|
2821
2854
|
shadcn: "migrate",
|
|
2822
2855
|
"teamix-evo": "update",
|
|
2823
|
-
other:
|
|
2856
|
+
other: "graft"
|
|
2824
2857
|
};
|
|
2825
2858
|
function assertCommandPrecondition(command, state) {
|
|
2826
2859
|
const expected = VALID_STATES[command];
|
|
@@ -2834,13 +2867,6 @@ function assertCommandPrecondition(command, state) {
|
|
|
2834
2867
|
if (suggestion) {
|
|
2835
2868
|
const suggestionLabel = COMMAND_LABELS[suggestion];
|
|
2836
2869
|
logger.info(`\u5EFA\u8BAE\u4F7F\u7528\uFF1Ateamix-evo ${suggestion}\uFF08${suggestionLabel}\uFF09`);
|
|
2837
|
-
} else {
|
|
2838
|
-
logger.info(
|
|
2839
|
-
"\u5F53\u524D\u9879\u76EE\u7C7B\u578B\u6682\u4E0D\u652F\u6301\u76F4\u63A5\u63A5\u5165\u3002"
|
|
2840
|
-
);
|
|
2841
|
-
logger.info(
|
|
2842
|
-
"\u5EFA\u8BAE\uFF1A\u5148\u7528 teamix-evo init \u521D\u59CB\u5316 Teamix Evo \u5957\u4EF6\uFF08\u7A7A\u76EE\u5F55\uFF09\uFF0C\u7136\u540E\u5BF9\u65E7\u9879\u76EE\u8FDB\u884C\u91CD\u6784\u3002"
|
|
2843
|
-
);
|
|
2844
2870
|
}
|
|
2845
2871
|
process.exitCode = 1;
|
|
2846
2872
|
}
|
|
@@ -2892,8 +2918,8 @@ var STYLELINT_CONFIG_CANDIDATES = [
|
|
|
2892
2918
|
];
|
|
2893
2919
|
async function isDir(target) {
|
|
2894
2920
|
try {
|
|
2895
|
-
const
|
|
2896
|
-
return
|
|
2921
|
+
const stat4 = await fs15.stat(target);
|
|
2922
|
+
return stat4.isDirectory();
|
|
2897
2923
|
} catch {
|
|
2898
2924
|
return false;
|
|
2899
2925
|
}
|
|
@@ -3117,8 +3143,30 @@ async function detectStylelintConfig(cwd) {
|
|
|
3117
3143
|
};
|
|
3118
3144
|
}
|
|
3119
3145
|
|
|
3120
|
-
// src/core/
|
|
3146
|
+
// src/core/html-theme-patch.ts
|
|
3121
3147
|
import * as path17 from "path";
|
|
3148
|
+
async function patchHtmlDataTheme(projectRoot, variant) {
|
|
3149
|
+
const htmlPath = path17.join(projectRoot, "index.html");
|
|
3150
|
+
const content = await readFileOrNull(htmlPath);
|
|
3151
|
+
if (content === null) {
|
|
3152
|
+
return { status: "not-found", htmlPath };
|
|
3153
|
+
}
|
|
3154
|
+
if (/data-theme\s*=/.test(content)) {
|
|
3155
|
+
return { status: "already-set", htmlPath };
|
|
3156
|
+
}
|
|
3157
|
+
const patched = content.replace(
|
|
3158
|
+
/<html([^>]*)>/,
|
|
3159
|
+
`<html$1 data-theme="${variant}">`
|
|
3160
|
+
);
|
|
3161
|
+
if (patched === content) {
|
|
3162
|
+
return { status: "not-found", htmlPath };
|
|
3163
|
+
}
|
|
3164
|
+
await writeFileSafe(htmlPath, patched);
|
|
3165
|
+
return { status: "patched", htmlPath };
|
|
3166
|
+
}
|
|
3167
|
+
|
|
3168
|
+
// src/core/meta-installer.ts
|
|
3169
|
+
import * as path18 from "path";
|
|
3122
3170
|
import * as fs16 from "fs/promises";
|
|
3123
3171
|
import { createRequire as createRequire5 } from "module";
|
|
3124
3172
|
import {
|
|
@@ -3129,11 +3177,11 @@ var require6 = createRequire5(import.meta.url);
|
|
|
3129
3177
|
var META_DIR = "meta";
|
|
3130
3178
|
function resolvePackageRoot4(packageName) {
|
|
3131
3179
|
const pkgJsonPath = require6.resolve(`${packageName}/package.json`);
|
|
3132
|
-
return
|
|
3180
|
+
return path18.dirname(pkgJsonPath);
|
|
3133
3181
|
}
|
|
3134
3182
|
function getMetaDir(projectRoot, category) {
|
|
3135
|
-
const base =
|
|
3136
|
-
return category ?
|
|
3183
|
+
const base = path18.join(getTeamixDir(projectRoot), META_DIR);
|
|
3184
|
+
return category ? path18.join(base, category) : base;
|
|
3137
3185
|
}
|
|
3138
3186
|
async function landUiMeta(projectRoot) {
|
|
3139
3187
|
const packageRoot = resolvePackageRoot4("@teamix-evo/ui");
|
|
@@ -3147,7 +3195,7 @@ async function landUiMeta(projectRoot) {
|
|
|
3147
3195
|
}
|
|
3148
3196
|
async function landBizUiMeta(projectRoot, variant) {
|
|
3149
3197
|
const packageRoot = resolvePackageRoot4("@teamix-evo/biz-ui");
|
|
3150
|
-
const variantRoot =
|
|
3198
|
+
const variantRoot = path18.join(packageRoot, "variants", variant);
|
|
3151
3199
|
const manifest = await loadVariantUiPackageManifest2(variantRoot);
|
|
3152
3200
|
return landManifestMeta({
|
|
3153
3201
|
projectRoot,
|
|
@@ -3161,8 +3209,8 @@ async function landManifestMeta(opts) {
|
|
|
3161
3209
|
await ensureTeamixDir(projectRoot);
|
|
3162
3210
|
const metaDir = getMetaDir(projectRoot, category);
|
|
3163
3211
|
await ensureDir(metaDir);
|
|
3164
|
-
const manifestDest =
|
|
3165
|
-
const manifestSrc =
|
|
3212
|
+
const manifestDest = path18.join(metaDir, "manifest.json");
|
|
3213
|
+
const manifestSrc = path18.join(packageRoot, "manifest.json");
|
|
3166
3214
|
await fs16.copyFile(manifestSrc, manifestDest);
|
|
3167
3215
|
logger.debug(`meta: copied manifest.json \u2192 ${manifestDest}`);
|
|
3168
3216
|
let written = 0;
|
|
@@ -3170,8 +3218,8 @@ async function landManifestMeta(opts) {
|
|
|
3170
3218
|
for (const entry of manifest.entries) {
|
|
3171
3219
|
if (!entry.meta) continue;
|
|
3172
3220
|
total++;
|
|
3173
|
-
const srcPath =
|
|
3174
|
-
const destPath =
|
|
3221
|
+
const srcPath = path18.join(packageRoot, entry.meta);
|
|
3222
|
+
const destPath = path18.join(metaDir, `${entry.id}.md`);
|
|
3175
3223
|
try {
|
|
3176
3224
|
await fs16.copyFile(srcPath, destPath);
|
|
3177
3225
|
written++;
|
|
@@ -3197,17 +3245,17 @@ async function landManifestMeta(opts) {
|
|
|
3197
3245
|
|
|
3198
3246
|
// src/core/deps-install.ts
|
|
3199
3247
|
import * as fs17 from "fs/promises";
|
|
3200
|
-
import * as
|
|
3248
|
+
import * as path19 from "path";
|
|
3201
3249
|
import { exec } from "child_process";
|
|
3202
3250
|
import { promisify } from "util";
|
|
3203
3251
|
var execAsync = promisify(exec);
|
|
3204
3252
|
async function detectPackageManager(projectRoot) {
|
|
3205
|
-
if (await fileExists(
|
|
3206
|
-
if (await fileExists(
|
|
3253
|
+
if (await fileExists(path19.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
3254
|
+
if (await fileExists(path19.join(projectRoot, "pnpm-workspace.yaml")))
|
|
3207
3255
|
return "pnpm";
|
|
3208
|
-
if (await fileExists(
|
|
3209
|
-
if (await fileExists(
|
|
3210
|
-
if (await fileExists(
|
|
3256
|
+
if (await fileExists(path19.join(projectRoot, "bun.lockb"))) return "bun";
|
|
3257
|
+
if (await fileExists(path19.join(projectRoot, "bun.lock"))) return "bun";
|
|
3258
|
+
if (await fileExists(path19.join(projectRoot, "yarn.lock"))) return "yarn";
|
|
3211
3259
|
return "npm";
|
|
3212
3260
|
}
|
|
3213
3261
|
function getInstallCommand(pm) {
|
|
@@ -3224,7 +3272,7 @@ function getInstallCommand(pm) {
|
|
|
3224
3272
|
}
|
|
3225
3273
|
async function installProjectDeps(options) {
|
|
3226
3274
|
const { projectRoot, npmDependencies, skipInstall = false } = options;
|
|
3227
|
-
const pkgPath =
|
|
3275
|
+
const pkgPath = path19.join(projectRoot, "package.json");
|
|
3228
3276
|
const raw = await readFileOrNull(pkgPath);
|
|
3229
3277
|
if (!raw) {
|
|
3230
3278
|
throw new Error(
|
|
@@ -3316,18 +3364,18 @@ ${stepLines}
|
|
|
3316
3364
|
|
|
3317
3365
|
// src/core/file-changes.ts
|
|
3318
3366
|
import * as fs18 from "fs/promises";
|
|
3319
|
-
import * as
|
|
3367
|
+
import * as path20 from "path";
|
|
3320
3368
|
function toRelativePosix(p, projectRoot) {
|
|
3321
3369
|
let rel2 = p;
|
|
3322
|
-
if (
|
|
3323
|
-
rel2 =
|
|
3370
|
+
if (path20.isAbsolute(p)) {
|
|
3371
|
+
rel2 = path20.relative(projectRoot, p);
|
|
3324
3372
|
}
|
|
3325
|
-
return rel2.split(
|
|
3373
|
+
return rel2.split(path20.sep).join("/");
|
|
3326
3374
|
}
|
|
3327
3375
|
|
|
3328
3376
|
// src/core/project-init.ts
|
|
3329
3377
|
import * as fsNode from "fs/promises";
|
|
3330
|
-
import * as
|
|
3378
|
+
import * as path21 from "path";
|
|
3331
3379
|
var CRITICAL_STEPS = /* @__PURE__ */ new Set([
|
|
3332
3380
|
"tokens",
|
|
3333
3381
|
"skills",
|
|
@@ -3395,6 +3443,38 @@ async function runProjectInit(options) {
|
|
|
3395
3443
|
recordFailure("tokens", err);
|
|
3396
3444
|
}
|
|
3397
3445
|
}
|
|
3446
|
+
if (dryRun) {
|
|
3447
|
+
record({
|
|
3448
|
+
name: "html-theme",
|
|
3449
|
+
status: "planned",
|
|
3450
|
+
detail: `patchHtmlDataTheme(variant=${variant})`
|
|
3451
|
+
});
|
|
3452
|
+
} else if (aborted) {
|
|
3453
|
+
record({
|
|
3454
|
+
name: "html-theme",
|
|
3455
|
+
status: "skip",
|
|
3456
|
+
detail: "aborted: earlier critical step failed"
|
|
3457
|
+
});
|
|
3458
|
+
} else {
|
|
3459
|
+
try {
|
|
3460
|
+
const htmlResult = await patchHtmlDataTheme(projectRoot, variant);
|
|
3461
|
+
record({
|
|
3462
|
+
name: "html-theme",
|
|
3463
|
+
status: "ok",
|
|
3464
|
+
detail: htmlResult.status,
|
|
3465
|
+
changes: htmlResult.status === "patched" ? [
|
|
3466
|
+
{
|
|
3467
|
+
kind: "modified",
|
|
3468
|
+
path: "index.html",
|
|
3469
|
+
step: "html-theme",
|
|
3470
|
+
detail: `data-theme="${variant}"`
|
|
3471
|
+
}
|
|
3472
|
+
] : []
|
|
3473
|
+
});
|
|
3474
|
+
} catch (err) {
|
|
3475
|
+
recordFailure("html-theme", err);
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3398
3478
|
if (dryRun) {
|
|
3399
3479
|
record({
|
|
3400
3480
|
name: "skills",
|
|
@@ -3669,7 +3749,7 @@ async function runProjectInit(options) {
|
|
|
3669
3749
|
detail: "projectRoot does not exist"
|
|
3670
3750
|
});
|
|
3671
3751
|
} else {
|
|
3672
|
-
const giPath =
|
|
3752
|
+
const giPath = path21.join(projectRoot, ".gitignore");
|
|
3673
3753
|
let giContent = "";
|
|
3674
3754
|
try {
|
|
3675
3755
|
giContent = await fsNode.readFile(giPath, "utf-8");
|
|
@@ -3729,12 +3809,12 @@ async function runProjectInit(options) {
|
|
|
3729
3809
|
if (!dryRun && hasFailures) {
|
|
3730
3810
|
try {
|
|
3731
3811
|
const checklistContent = renderInitChecklist({ variant, status, steps });
|
|
3732
|
-
const checklistPath =
|
|
3812
|
+
const checklistPath = path21.join(
|
|
3733
3813
|
projectRoot,
|
|
3734
3814
|
".teamix-evo",
|
|
3735
3815
|
"init-checklist.md"
|
|
3736
3816
|
);
|
|
3737
|
-
await fsNode.mkdir(
|
|
3817
|
+
await fsNode.mkdir(path21.dirname(checklistPath), { recursive: true });
|
|
3738
3818
|
await fsNode.writeFile(checklistPath, checklistContent, "utf-8");
|
|
3739
3819
|
logger.info(" wrote .teamix-evo/init-checklist.md");
|
|
3740
3820
|
} catch {
|
|
@@ -3773,9 +3853,438 @@ function deriveLintChanges(result) {
|
|
|
3773
3853
|
return out;
|
|
3774
3854
|
}
|
|
3775
3855
|
|
|
3776
|
-
// src/core/
|
|
3777
|
-
import
|
|
3856
|
+
// src/core/graft-init.ts
|
|
3857
|
+
import { hasManagedRegion as hasManagedRegion3, replaceManagedRegion as replaceManagedRegion3 } from "@teamix-evo/registry";
|
|
3858
|
+
|
|
3859
|
+
// src/core/snapshot.ts
|
|
3778
3860
|
import * as fs19 from "fs/promises";
|
|
3861
|
+
import * as path22 from "path";
|
|
3862
|
+
var TEAMIX_DIR2 = ".teamix-evo";
|
|
3863
|
+
var SNAPSHOTS_DIR = ".snapshots";
|
|
3864
|
+
var META_FILE = "_meta.json";
|
|
3865
|
+
var DEFAULT_KEEP = 5;
|
|
3866
|
+
var SNAPSHOT_REASONS = ["init", "update", "switch", "restore", "graft", "manual"];
|
|
3867
|
+
function isoToFsSafe(iso) {
|
|
3868
|
+
return iso.replace(/[:.]/g, "-");
|
|
3869
|
+
}
|
|
3870
|
+
function fsSafeToIso(safe) {
|
|
3871
|
+
return safe.replace(
|
|
3872
|
+
/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})-(\d{3})(Z)$/,
|
|
3873
|
+
"$1T$2:$3:$4.$5$6"
|
|
3874
|
+
);
|
|
3875
|
+
}
|
|
3876
|
+
async function createSnapshot(projectRoot, opts = {}) {
|
|
3877
|
+
const teamixDir = path22.join(projectRoot, TEAMIX_DIR2);
|
|
3878
|
+
try {
|
|
3879
|
+
const stat4 = await fs19.stat(teamixDir);
|
|
3880
|
+
if (!stat4.isDirectory()) return null;
|
|
3881
|
+
} catch (err) {
|
|
3882
|
+
if (err.code === "ENOENT") return null;
|
|
3883
|
+
throw err;
|
|
3884
|
+
}
|
|
3885
|
+
const isoTs = (/* @__PURE__ */ new Date()).toISOString();
|
|
3886
|
+
const ts = isoToFsSafe(isoTs);
|
|
3887
|
+
const snapshotRoot = path22.join(teamixDir, SNAPSHOTS_DIR);
|
|
3888
|
+
const target = path22.join(snapshotRoot, ts);
|
|
3889
|
+
await fs19.mkdir(target, { recursive: true });
|
|
3890
|
+
const entries = await fs19.readdir(teamixDir, { withFileTypes: true });
|
|
3891
|
+
for (const entry of entries) {
|
|
3892
|
+
if (entry.name === SNAPSHOTS_DIR) continue;
|
|
3893
|
+
const src = path22.join(teamixDir, entry.name);
|
|
3894
|
+
const dst = path22.join(target, entry.name);
|
|
3895
|
+
await fs19.cp(src, dst, { recursive: true });
|
|
3896
|
+
}
|
|
3897
|
+
const meta = {
|
|
3898
|
+
ts: isoTs,
|
|
3899
|
+
reason: opts.reason ?? "manual"
|
|
3900
|
+
};
|
|
3901
|
+
await fs19.writeFile(
|
|
3902
|
+
path22.join(target, META_FILE),
|
|
3903
|
+
JSON.stringify(meta, null, 2) + "\n",
|
|
3904
|
+
"utf-8"
|
|
3905
|
+
);
|
|
3906
|
+
logger.debug(
|
|
3907
|
+
`Snapshot created \u2192 ${path22.relative(projectRoot, target)} (${meta.reason})`
|
|
3908
|
+
);
|
|
3909
|
+
const keep = opts.keep ?? DEFAULT_KEEP;
|
|
3910
|
+
await pruneSnapshots(projectRoot, keep, { protectedTs: opts.protectedTs });
|
|
3911
|
+
return { ts, path: target };
|
|
3912
|
+
}
|
|
3913
|
+
async function listSnapshots(projectRoot) {
|
|
3914
|
+
const snapshotRoot = path22.join(projectRoot, TEAMIX_DIR2, SNAPSHOTS_DIR);
|
|
3915
|
+
let entries;
|
|
3916
|
+
try {
|
|
3917
|
+
entries = await fs19.readdir(snapshotRoot, { withFileTypes: true });
|
|
3918
|
+
} catch (err) {
|
|
3919
|
+
if (err.code === "ENOENT") return [];
|
|
3920
|
+
throw err;
|
|
3921
|
+
}
|
|
3922
|
+
const result = [];
|
|
3923
|
+
for (const entry of entries) {
|
|
3924
|
+
if (!entry.isDirectory()) continue;
|
|
3925
|
+
const dir = path22.join(snapshotRoot, entry.name);
|
|
3926
|
+
let isoTs = null;
|
|
3927
|
+
let reason = null;
|
|
3928
|
+
try {
|
|
3929
|
+
const raw = await fs19.readFile(path22.join(dir, META_FILE), "utf-8");
|
|
3930
|
+
const parsed = JSON.parse(raw);
|
|
3931
|
+
if (typeof parsed.ts === "string") isoTs = parsed.ts;
|
|
3932
|
+
if (typeof parsed.reason === "string" && SNAPSHOT_REASONS.includes(
|
|
3933
|
+
parsed.reason
|
|
3934
|
+
)) {
|
|
3935
|
+
reason = parsed.reason;
|
|
3936
|
+
}
|
|
3937
|
+
} catch {
|
|
3938
|
+
isoTs = fsSafeToIso(entry.name);
|
|
3939
|
+
}
|
|
3940
|
+
result.push({ ts: entry.name, isoTs, reason, path: dir });
|
|
3941
|
+
}
|
|
3942
|
+
result.sort((a, b) => a.ts < b.ts ? 1 : a.ts > b.ts ? -1 : 0);
|
|
3943
|
+
return result;
|
|
3944
|
+
}
|
|
3945
|
+
async function pruneSnapshots(projectRoot, keep = DEFAULT_KEEP, opts = {}) {
|
|
3946
|
+
if (keep < 0)
|
|
3947
|
+
throw new Error(`pruneSnapshots: keep must be >= 0, got ${keep}`);
|
|
3948
|
+
const snapshots = await listSnapshots(projectRoot);
|
|
3949
|
+
if (snapshots.length <= keep) return [];
|
|
3950
|
+
const tail = snapshots.slice(keep);
|
|
3951
|
+
const toRemove = opts.protectedTs ? tail.filter((s) => s.ts !== opts.protectedTs) : tail;
|
|
3952
|
+
const removed = [];
|
|
3953
|
+
for (const snap of toRemove) {
|
|
3954
|
+
await fs19.rm(snap.path, { recursive: true, force: true });
|
|
3955
|
+
removed.push(snap.ts);
|
|
3956
|
+
logger.debug(`Pruned snapshot ${snap.ts}`);
|
|
3957
|
+
}
|
|
3958
|
+
return removed.reverse();
|
|
3959
|
+
}
|
|
3960
|
+
|
|
3961
|
+
// src/core/graft-init.ts
|
|
3962
|
+
import * as fsNode2 from "fs/promises";
|
|
3963
|
+
import * as path23 from "path";
|
|
3964
|
+
var CRITICAL_STEPS2 = /* @__PURE__ */ new Set([
|
|
3965
|
+
"ensure-teamix-dir",
|
|
3966
|
+
"tokens",
|
|
3967
|
+
"ui-init",
|
|
3968
|
+
"skills"
|
|
3969
|
+
]);
|
|
3970
|
+
var AGENTS_MD_GRAFT_MANAGED_ID = "teamix-evo-graft";
|
|
3971
|
+
var GITIGNORE_MARKER_START2 = "# >>> teamix-evo:managed >>>";
|
|
3972
|
+
var GITIGNORE_MARKER_END2 = "# <<< teamix-evo:managed <<<";
|
|
3973
|
+
var GITIGNORE_RULES2 = [
|
|
3974
|
+
"# Runtime artifacts (regenerable / archives)",
|
|
3975
|
+
".teamix-evo/.snapshots/",
|
|
3976
|
+
".teamix-evo/.backups/",
|
|
3977
|
+
".teamix-evo/.upgrade-staging/",
|
|
3978
|
+
".teamix-evo/.upgrade-hints/"
|
|
3979
|
+
];
|
|
3980
|
+
var LEGACY_LIB_META = {
|
|
3981
|
+
fusion: {
|
|
3982
|
+
displayName: "Fusion Design",
|
|
3983
|
+
imports: ["teamix/ui", "@alifd/next", "@ali/teamix-material"]
|
|
3984
|
+
},
|
|
3985
|
+
antd: {
|
|
3986
|
+
displayName: "Ant Design",
|
|
3987
|
+
imports: ["antd", "@ant-design/*"]
|
|
3988
|
+
},
|
|
3989
|
+
element: {
|
|
3990
|
+
displayName: "Element UI",
|
|
3991
|
+
imports: ["element-ui", "element-plus"]
|
|
3992
|
+
}
|
|
3993
|
+
};
|
|
3994
|
+
async function runGraftInit(options) {
|
|
3995
|
+
const {
|
|
3996
|
+
projectRoot,
|
|
3997
|
+
variant,
|
|
3998
|
+
legacyLib,
|
|
3999
|
+
onStep
|
|
4000
|
+
} = options;
|
|
4001
|
+
const ide = options.ide ?? "qoder";
|
|
4002
|
+
const ides = options.ides ?? ["qoder", "claude"];
|
|
4003
|
+
const scope = options.scope ?? "project";
|
|
4004
|
+
const steps = [];
|
|
4005
|
+
let aborted = false;
|
|
4006
|
+
function record(step) {
|
|
4007
|
+
steps.push(step);
|
|
4008
|
+
onStep?.(step);
|
|
4009
|
+
}
|
|
4010
|
+
function recordFailure(name, err) {
|
|
4011
|
+
const message = getErrorMessage(err);
|
|
4012
|
+
record({ name, status: "fail", detail: message });
|
|
4013
|
+
if (CRITICAL_STEPS2.has(name)) aborted = true;
|
|
4014
|
+
}
|
|
4015
|
+
try {
|
|
4016
|
+
await ensureTeamixDir(projectRoot);
|
|
4017
|
+
record({ name: "ensure-teamix-dir", status: "ok" });
|
|
4018
|
+
} catch (err) {
|
|
4019
|
+
recordFailure("ensure-teamix-dir", err);
|
|
4020
|
+
}
|
|
4021
|
+
if (!aborted) {
|
|
4022
|
+
try {
|
|
4023
|
+
const snap = await createSnapshot(projectRoot, { reason: "graft" });
|
|
4024
|
+
record({
|
|
4025
|
+
name: "snapshot",
|
|
4026
|
+
status: "ok",
|
|
4027
|
+
detail: snap ? `snapshot ${snap.ts}` : "empty .teamix-evo/ \u2014 nothing to snapshot"
|
|
4028
|
+
});
|
|
4029
|
+
} catch (err) {
|
|
4030
|
+
recordFailure("snapshot", err);
|
|
4031
|
+
}
|
|
4032
|
+
} else {
|
|
4033
|
+
record({ name: "snapshot", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4034
|
+
}
|
|
4035
|
+
if (!aborted) {
|
|
4036
|
+
try {
|
|
4037
|
+
const result = await runTokensInit({ projectRoot, variant, ide });
|
|
4038
|
+
const detail = result.status === "installed" ? `${result.packageName}@${result.version} (${result.count} files)` : result.status;
|
|
4039
|
+
record({ name: "tokens", status: "ok", detail });
|
|
4040
|
+
} catch (err) {
|
|
4041
|
+
recordFailure("tokens", err);
|
|
4042
|
+
}
|
|
4043
|
+
} else {
|
|
4044
|
+
record({ name: "tokens", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4045
|
+
}
|
|
4046
|
+
if (!aborted) {
|
|
4047
|
+
try {
|
|
4048
|
+
const initResult = await runUiInit({ projectRoot, ide });
|
|
4049
|
+
record({
|
|
4050
|
+
name: "ui-init",
|
|
4051
|
+
status: "ok",
|
|
4052
|
+
detail: initResult.status === "installed" ? "config.json packages.ui written" : initResult.status
|
|
4053
|
+
});
|
|
4054
|
+
} catch (err) {
|
|
4055
|
+
recordFailure("ui-init", err);
|
|
4056
|
+
}
|
|
4057
|
+
} else {
|
|
4058
|
+
record({ name: "ui-init", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4059
|
+
}
|
|
4060
|
+
const collectedNpmDeps = {};
|
|
4061
|
+
if (!aborted) {
|
|
4062
|
+
try {
|
|
4063
|
+
const { manifest } = await loadUiData("@teamix-evo/ui");
|
|
4064
|
+
const allIds = manifest.entries.map((e) => e.id);
|
|
4065
|
+
const addResult = await runUiAdd({
|
|
4066
|
+
projectRoot,
|
|
4067
|
+
ids: allIds,
|
|
4068
|
+
overwrite: true
|
|
4069
|
+
});
|
|
4070
|
+
record({
|
|
4071
|
+
name: "ui-add",
|
|
4072
|
+
status: "ok",
|
|
4073
|
+
detail: `${addResult.orderedIds.length} entries (${addResult.written} written, ${addResult.skipped} skipped)`
|
|
4074
|
+
});
|
|
4075
|
+
Object.assign(collectedNpmDeps, addResult.npmDependencies);
|
|
4076
|
+
} catch (err) {
|
|
4077
|
+
recordFailure("ui-add", err);
|
|
4078
|
+
}
|
|
4079
|
+
} else {
|
|
4080
|
+
record({ name: "ui-add", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4081
|
+
}
|
|
4082
|
+
if (!aborted) {
|
|
4083
|
+
try {
|
|
4084
|
+
const listing = await listBizUiEntries(variant);
|
|
4085
|
+
if (listing.entries.length === 0) {
|
|
4086
|
+
record({
|
|
4087
|
+
name: "biz-ui-add",
|
|
4088
|
+
status: "skip",
|
|
4089
|
+
detail: `no biz-ui entries for variant "${variant}"`
|
|
4090
|
+
});
|
|
4091
|
+
} else {
|
|
4092
|
+
const allIds = listing.entries.map((e) => e.id);
|
|
4093
|
+
const result = await runBizUiAdd({
|
|
4094
|
+
projectRoot,
|
|
4095
|
+
variant,
|
|
4096
|
+
ids: allIds,
|
|
4097
|
+
overwrite: true
|
|
4098
|
+
});
|
|
4099
|
+
record({
|
|
4100
|
+
name: "biz-ui-add",
|
|
4101
|
+
status: "ok",
|
|
4102
|
+
detail: `${result.orderedIds.length} entries (${result.written} written, ${result.skipped} skipped)`
|
|
4103
|
+
});
|
|
4104
|
+
if (result.npmDependencies) {
|
|
4105
|
+
Object.assign(collectedNpmDeps, result.npmDependencies);
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
} catch (err) {
|
|
4109
|
+
recordFailure("biz-ui-add", err);
|
|
4110
|
+
}
|
|
4111
|
+
} else {
|
|
4112
|
+
record({ name: "biz-ui-add", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4113
|
+
}
|
|
4114
|
+
if (!aborted && Object.keys(collectedNpmDeps).length > 0) {
|
|
4115
|
+
try {
|
|
4116
|
+
await installProjectDeps({
|
|
4117
|
+
projectRoot,
|
|
4118
|
+
npmDependencies: collectedNpmDeps,
|
|
4119
|
+
skipInstall: options.skipInstall ?? false
|
|
4120
|
+
});
|
|
4121
|
+
} catch (err) {
|
|
4122
|
+
logger.warn(
|
|
4123
|
+
`\u5B89\u88C5 ui/biz-ui \u4F20\u9012\u4F9D\u8D56\u5931\u8D25\uFF1A${getErrorMessage(err)}\uFF08\u53EF\u624B\u52A8\u8FD0\u884C \`npm install\` \u91CD\u8BD5\uFF09`
|
|
4124
|
+
);
|
|
4125
|
+
}
|
|
4126
|
+
}
|
|
4127
|
+
if (!aborted) {
|
|
4128
|
+
try {
|
|
4129
|
+
const result = await runSkillsInit({ projectRoot, ides, scope, ide });
|
|
4130
|
+
if (result.status === "already-initialized") {
|
|
4131
|
+
record({ name: "skills", status: "ok", detail: "already-initialized" });
|
|
4132
|
+
} else {
|
|
4133
|
+
record({
|
|
4134
|
+
name: "skills",
|
|
4135
|
+
status: "ok",
|
|
4136
|
+
detail: `${result.skillCount} skills, ${result.fileCount} files`
|
|
4137
|
+
});
|
|
4138
|
+
}
|
|
4139
|
+
} catch (err) {
|
|
4140
|
+
recordFailure("skills", err);
|
|
4141
|
+
}
|
|
4142
|
+
} else {
|
|
4143
|
+
record({ name: "skills", status: "skip", detail: "aborted: earlier critical step failed" });
|
|
4144
|
+
}
|
|
4145
|
+
if (!aborted) {
|
|
4146
|
+
try {
|
|
4147
|
+
const result = await runGenerateAgentsMd({
|
|
4148
|
+
projectRoot,
|
|
4149
|
+
variant,
|
|
4150
|
+
skillIds: [
|
|
4151
|
+
`teamix-evo-design-${variant}`,
|
|
4152
|
+
`teamix-evo-code-${variant}`
|
|
4153
|
+
],
|
|
4154
|
+
globalSkillIds: ["teamix-evo-manage"],
|
|
4155
|
+
mode: "merge-managed"
|
|
4156
|
+
});
|
|
4157
|
+
record({
|
|
4158
|
+
name: "agents-md",
|
|
4159
|
+
status: "ok",
|
|
4160
|
+
detail: `${result.skillCount} skill index (${result.merge})`
|
|
4161
|
+
});
|
|
4162
|
+
} catch (err) {
|
|
4163
|
+
recordFailure("agents-md", err);
|
|
4164
|
+
}
|
|
4165
|
+
} else {
|
|
4166
|
+
record({ name: "agents-md", status: "skip", detail: "aborted" });
|
|
4167
|
+
}
|
|
4168
|
+
if (!aborted) {
|
|
4169
|
+
try {
|
|
4170
|
+
const agentsMdPath = path23.join(projectRoot, "AGENTS.md");
|
|
4171
|
+
const existing = await readFileOrNull(agentsMdPath) ?? "";
|
|
4172
|
+
const meta = LEGACY_LIB_META[legacyLib] ?? {
|
|
4173
|
+
displayName: legacyLib,
|
|
4174
|
+
imports: [legacyLib]
|
|
4175
|
+
};
|
|
4176
|
+
const importsStr = meta.imports.map((i) => `\`${i}\``).join("\u3001");
|
|
4177
|
+
const graftBody = renderGraftManagedBody(meta.displayName, importsStr);
|
|
4178
|
+
let output;
|
|
4179
|
+
if (hasManagedRegion3(existing, AGENTS_MD_GRAFT_MANAGED_ID)) {
|
|
4180
|
+
output = replaceManagedRegion3(
|
|
4181
|
+
existing,
|
|
4182
|
+
AGENTS_MD_GRAFT_MANAGED_ID,
|
|
4183
|
+
graftBody
|
|
4184
|
+
);
|
|
4185
|
+
} else {
|
|
4186
|
+
const wrapped = wrapGraftManagedBlock(graftBody);
|
|
4187
|
+
output = existing.trimEnd() + "\n\n" + wrapped + "\n";
|
|
4188
|
+
}
|
|
4189
|
+
await fsNode2.writeFile(agentsMdPath, output, "utf-8");
|
|
4190
|
+
record({ name: "agents-md-graft", status: "ok", detail: `dual-stack rules for ${legacyLib}` });
|
|
4191
|
+
} catch (err) {
|
|
4192
|
+
recordFailure("agents-md-graft", err);
|
|
4193
|
+
}
|
|
4194
|
+
} else {
|
|
4195
|
+
record({ name: "agents-md-graft", status: "skip", detail: "aborted" });
|
|
4196
|
+
}
|
|
4197
|
+
if (!aborted) {
|
|
4198
|
+
try {
|
|
4199
|
+
const uiResult = await landUiMeta(projectRoot);
|
|
4200
|
+
const bizResult = await landBizUiMeta(projectRoot, variant);
|
|
4201
|
+
record({
|
|
4202
|
+
name: "meta-landing",
|
|
4203
|
+
status: "ok",
|
|
4204
|
+
detail: `ui: ${uiResult.metaFilesWritten}/${uiResult.metaFilesTotal}, biz-ui: ${bizResult.metaFilesWritten}/${bizResult.metaFilesTotal}`
|
|
4205
|
+
});
|
|
4206
|
+
} catch (err) {
|
|
4207
|
+
recordFailure("meta-landing", err);
|
|
4208
|
+
}
|
|
4209
|
+
} else {
|
|
4210
|
+
record({ name: "meta-landing", status: "skip", detail: "aborted" });
|
|
4211
|
+
}
|
|
4212
|
+
if (!aborted) {
|
|
4213
|
+
try {
|
|
4214
|
+
const config = await readProjectConfig(projectRoot);
|
|
4215
|
+
if (config) {
|
|
4216
|
+
config.mode = "graft";
|
|
4217
|
+
config.legacyLib = legacyLib;
|
|
4218
|
+
await writeProjectConfig(projectRoot, config);
|
|
4219
|
+
record({ name: "config-mode", status: "ok", detail: `mode=graft, legacyLib=${legacyLib}` });
|
|
4220
|
+
} else {
|
|
4221
|
+
record({ name: "config-mode", status: "skip", detail: "no config.json found to patch" });
|
|
4222
|
+
}
|
|
4223
|
+
} catch (err) {
|
|
4224
|
+
recordFailure("config-mode", err);
|
|
4225
|
+
}
|
|
4226
|
+
} else {
|
|
4227
|
+
record({ name: "config-mode", status: "skip", detail: "aborted" });
|
|
4228
|
+
}
|
|
4229
|
+
if (!aborted) {
|
|
4230
|
+
try {
|
|
4231
|
+
const giPath = path23.join(projectRoot, ".gitignore");
|
|
4232
|
+
let giContent = "";
|
|
4233
|
+
try {
|
|
4234
|
+
giContent = await fsNode2.readFile(giPath, "utf-8");
|
|
4235
|
+
} catch {
|
|
4236
|
+
}
|
|
4237
|
+
if (giContent.includes(GITIGNORE_MARKER_START2)) {
|
|
4238
|
+
record({ name: "gitignore", status: "skip", detail: "teamix-evo markers already present" });
|
|
4239
|
+
} else {
|
|
4240
|
+
const block = [
|
|
4241
|
+
"",
|
|
4242
|
+
GITIGNORE_MARKER_START2,
|
|
4243
|
+
...GITIGNORE_RULES2,
|
|
4244
|
+
GITIGNORE_MARKER_END2,
|
|
4245
|
+
""
|
|
4246
|
+
].join("\n");
|
|
4247
|
+
const separator = giContent.length > 0 && !giContent.endsWith("\n") ? "\n" : "";
|
|
4248
|
+
await fsNode2.writeFile(giPath, giContent + separator + block, "utf-8");
|
|
4249
|
+
record({
|
|
4250
|
+
name: "gitignore",
|
|
4251
|
+
status: "ok",
|
|
4252
|
+
detail: `${GITIGNORE_RULES2.filter((r) => r && !r.startsWith("#")).length} rules appended`
|
|
4253
|
+
});
|
|
4254
|
+
}
|
|
4255
|
+
} catch (err) {
|
|
4256
|
+
recordFailure("gitignore", err);
|
|
4257
|
+
}
|
|
4258
|
+
} else {
|
|
4259
|
+
record({ name: "gitignore", status: "skip", detail: "aborted" });
|
|
4260
|
+
}
|
|
4261
|
+
const status = steps.some((s) => s.status === "fail") ? "partial" : "success";
|
|
4262
|
+
return { status, steps };
|
|
4263
|
+
}
|
|
4264
|
+
function renderGraftManagedBody(legacyLibName, legacyImports) {
|
|
4265
|
+
return `## \u53CC\u6808\u7814\u53D1\u89C4\u5219
|
|
4266
|
+
|
|
4267
|
+
\u672C\u9879\u76EE\u540C\u65F6\u5B58\u5728 ${legacyLibName}\uFF08\u65E7\u6808\uFF09\u548C teamix-evo\uFF08\u65B0\u6808\uFF09\u4E24\u5957\u6280\u672F\u6808\u3002
|
|
4268
|
+
|
|
4269
|
+
### \u5224\u65AD\u89C4\u5219\u2014\u2014\u901A\u8FC7 import \u8BED\u53E5\u8BC6\u522B
|
|
4270
|
+
- \u6587\u4EF6\u4E2D import \u4E86 ${legacyImports} \u2192 **\u65E7\u6808**\uFF0C\u6309 ${legacyLibName} \u89C4\u8303\u7814\u53D1\uFF0C**\u8DF3\u8FC7** teamix-evo \u7684 design / code skill
|
|
4271
|
+
- \u6587\u4EF6\u4E2D import \u4E86 \`@/components/ui\`\u3001\u4F7F\u7528 Tailwind class \u2192 **\u65B0\u6808**\uFF0C\u6B63\u5E38\u89E6\u53D1 teamix-evo design / code skill
|
|
4272
|
+
- \u65B0\u5EFA\u9875\u9762 \u2192 \u9ED8\u8BA4\u4F7F\u7528\u65B0\u6808\uFF08teamix-evo\uFF09
|
|
4273
|
+
|
|
4274
|
+
### \u7981\u6B62\u4E8B\u9879
|
|
4275
|
+
- \u7981\u6B62\u5728\u65E7\u6808\u6587\u4EF6\u4E2D\u5F15\u5165 \`@/components/ui\` \u6216 Tailwind class
|
|
4276
|
+
- \u7981\u6B62\u5728\u65B0\u6808\u6587\u4EF6\u4E2D\u5F15\u5165 ${legacyImports}
|
|
4277
|
+
- \u7981\u6B62\u5728\u540C\u4E00\u6587\u4EF6\u4E2D\u6DF7\u7528\u4E24\u5957\u7EC4\u4EF6\u5E93`;
|
|
4278
|
+
}
|
|
4279
|
+
function wrapGraftManagedBlock(body) {
|
|
4280
|
+
return `<!-- teamix-evo:managed:start id="${AGENTS_MD_GRAFT_MANAGED_ID}" -->
|
|
4281
|
+
${body}
|
|
4282
|
+
<!-- teamix-evo:managed:end id="${AGENTS_MD_GRAFT_MANAGED_ID}" -->`;
|
|
4283
|
+
}
|
|
4284
|
+
|
|
4285
|
+
// src/core/installer.ts
|
|
4286
|
+
import * as path24 from "path";
|
|
4287
|
+
import * as fs20 from "fs/promises";
|
|
3779
4288
|
async function installResources(options) {
|
|
3780
4289
|
const { projectRoot, manifest, data, variantDir, packageRoot } = options;
|
|
3781
4290
|
const installedResources = [];
|
|
@@ -3812,13 +4321,13 @@ async function installSingleResource(resource, projectRoot, data, variantDir, pa
|
|
|
3812
4321
|
variantDir,
|
|
3813
4322
|
packageRoot
|
|
3814
4323
|
);
|
|
3815
|
-
const targetPath =
|
|
4324
|
+
const targetPath = path24.join(projectRoot, resource.target);
|
|
3816
4325
|
let content;
|
|
3817
4326
|
if (resource.template) {
|
|
3818
4327
|
const templateContent = await loadTemplateFile(sourcePath);
|
|
3819
4328
|
content = renderTemplate(templateContent, data);
|
|
3820
4329
|
} else {
|
|
3821
|
-
content = await
|
|
4330
|
+
content = await fs20.readFile(sourcePath, "utf-8");
|
|
3822
4331
|
}
|
|
3823
4332
|
await writeFileSafe(targetPath, content);
|
|
3824
4333
|
const hash = computeHash(content);
|
|
@@ -3836,13 +4345,13 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
3836
4345
|
variantDir,
|
|
3837
4346
|
packageRoot
|
|
3838
4347
|
);
|
|
3839
|
-
const targetDir =
|
|
4348
|
+
const targetDir = path24.join(projectRoot, resource.target);
|
|
3840
4349
|
const results = [];
|
|
3841
4350
|
await ensureDir(targetDir);
|
|
3842
4351
|
const entries = await walkDir(sourcePath);
|
|
3843
4352
|
for (const entry of entries) {
|
|
3844
|
-
const relPath =
|
|
3845
|
-
let targetFile =
|
|
4353
|
+
const relPath = path24.relative(sourcePath, entry);
|
|
4354
|
+
let targetFile = path24.join(targetDir, relPath);
|
|
3846
4355
|
if (resource.template && targetFile.endsWith(".hbs")) {
|
|
3847
4356
|
targetFile = targetFile.slice(0, -4);
|
|
3848
4357
|
}
|
|
@@ -3851,11 +4360,11 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
3851
4360
|
const templateContent = await loadTemplateFile(entry);
|
|
3852
4361
|
content = renderTemplate(templateContent, data);
|
|
3853
4362
|
} else {
|
|
3854
|
-
content = await
|
|
4363
|
+
content = await fs20.readFile(entry, "utf-8");
|
|
3855
4364
|
}
|
|
3856
4365
|
await writeFileSafe(targetFile, content);
|
|
3857
4366
|
const hash = computeHash(content);
|
|
3858
|
-
const targetRel =
|
|
4367
|
+
const targetRel = path24.relative(projectRoot, targetFile);
|
|
3859
4368
|
results.push({
|
|
3860
4369
|
id: `${resource.id}:${relPath}`,
|
|
3861
4370
|
target: targetRel,
|
|
@@ -3868,25 +4377,25 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
3868
4377
|
}
|
|
3869
4378
|
|
|
3870
4379
|
// src/core/registry-client.ts
|
|
3871
|
-
import * as
|
|
3872
|
-
import * as
|
|
4380
|
+
import * as path25 from "path";
|
|
4381
|
+
import * as fs21 from "fs/promises";
|
|
3873
4382
|
import { createRequire as createRequire6 } from "module";
|
|
3874
4383
|
import { loadVariantManifest } from "@teamix-evo/registry";
|
|
3875
4384
|
var require7 = createRequire6(import.meta.url);
|
|
3876
4385
|
function resolvePackageRoot5(packageName) {
|
|
3877
4386
|
const pkgJsonPath = require7.resolve(`${packageName}/package.json`);
|
|
3878
|
-
return
|
|
4387
|
+
return path25.dirname(pkgJsonPath);
|
|
3879
4388
|
}
|
|
3880
4389
|
async function loadVariantData(packageName, variant) {
|
|
3881
4390
|
const packageRoot = resolvePackageRoot5(packageName);
|
|
3882
|
-
const variantDir =
|
|
4391
|
+
const variantDir = path25.join(packageRoot, "library", variant);
|
|
3883
4392
|
logger.debug(`Resolved variant dir: ${variantDir}`);
|
|
3884
4393
|
logger.debug(`Package root: ${packageRoot}`);
|
|
3885
4394
|
const manifest = await loadVariantManifest(variantDir);
|
|
3886
4395
|
let data = {};
|
|
3887
|
-
const dataPath =
|
|
4396
|
+
const dataPath = path25.join(variantDir, "_data.json");
|
|
3888
4397
|
try {
|
|
3889
|
-
const raw = await
|
|
4398
|
+
const raw = await fs21.readFile(dataPath, "utf-8");
|
|
3890
4399
|
data = JSON.parse(raw);
|
|
3891
4400
|
} catch (err) {
|
|
3892
4401
|
if (err.code !== "ENOENT") {
|
|
@@ -3922,6 +4431,7 @@ export {
|
|
|
3922
4431
|
removeUiFiles,
|
|
3923
4432
|
runBizUiAdd,
|
|
3924
4433
|
runGenerateAgentsMd,
|
|
4434
|
+
runGraftInit,
|
|
3925
4435
|
runLintInit,
|
|
3926
4436
|
runProjectInit,
|
|
3927
4437
|
runSkillsAdd,
|