teamix-evo 0.3.1 → 0.4.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 +16 -16
- package/dist/core/index.d.ts +59 -29
- package/dist/core/index.js +296 -256
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +888 -366
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/core/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
// src/core/
|
|
2
|
-
import * as
|
|
1
|
+
// src/core/tokens-init.ts
|
|
2
|
+
import * as path8 from "path";
|
|
3
3
|
import * as fs6 from "fs/promises";
|
|
4
4
|
import { createRequire as createRequire2 } from "module";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
mergeDefaultAndVariant
|
|
6
|
+
loadTokensPackageManifest,
|
|
7
|
+
getVariantEntry
|
|
9
8
|
} from "@teamix-evo/registry";
|
|
10
9
|
|
|
11
10
|
// src/utils/fs.ts
|
|
@@ -90,71 +89,22 @@ function computeHash(content) {
|
|
|
90
89
|
return `sha256:${hash}`;
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
// src/core/design-pack-classify.ts
|
|
94
|
-
import * as path2 from "path";
|
|
95
|
-
var TEAMIX_DIR = ".teamix-evo/design";
|
|
96
|
-
var TOKENS_DIR = ".teamix-evo/tokens";
|
|
97
|
-
var TOKENS_PACK_PREFIX = "foundations/tokens/";
|
|
98
|
-
var ROOT_MANAGED_FILES = {
|
|
99
|
-
"DESIGN.md": { target: "DESIGN.md", managedRegions: ["core"] },
|
|
100
|
-
"AGENTS.md": { target: "AGENTS.md", managedRegions: ["teamix-evo"] },
|
|
101
|
-
"CLAUDE.md": { target: "CLAUDE.md", managedRegions: ["teamix-evo"] }
|
|
102
|
-
};
|
|
103
|
-
var FROZEN_FILES = /* @__PURE__ */ new Set([
|
|
104
|
-
"foundations/tokens/tokens.overrides.css"
|
|
105
|
-
]);
|
|
106
|
-
function classifyPackFile(relPath) {
|
|
107
|
-
if (path2.basename(relPath) === "README.md") {
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
const rootManaged = ROOT_MANAGED_FILES[relPath];
|
|
111
|
-
if (rootManaged) {
|
|
112
|
-
return {
|
|
113
|
-
target: rootManaged.target,
|
|
114
|
-
strategy: "managed",
|
|
115
|
-
managedRegions: rootManaged.managedRegions,
|
|
116
|
-
isFrozen: false
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
if (relPath.startsWith(TOKENS_PACK_PREFIX)) {
|
|
120
|
-
const rel2 = relPath.slice(TOKENS_PACK_PREFIX.length);
|
|
121
|
-
const target = path2.posix.join(TOKENS_DIR, rel2);
|
|
122
|
-
if (FROZEN_FILES.has(relPath)) {
|
|
123
|
-
return { target, strategy: "frozen", isFrozen: true };
|
|
124
|
-
}
|
|
125
|
-
return { target, strategy: "regenerable", isFrozen: false };
|
|
126
|
-
}
|
|
127
|
-
if (FROZEN_FILES.has(relPath)) {
|
|
128
|
-
return {
|
|
129
|
-
target: path2.posix.join(TEAMIX_DIR, relPath),
|
|
130
|
-
strategy: "frozen",
|
|
131
|
-
isFrozen: true
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
return {
|
|
135
|
-
target: path2.posix.join(TEAMIX_DIR, relPath),
|
|
136
|
-
strategy: "regenerable",
|
|
137
|
-
isFrozen: false
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
92
|
// src/core/state.ts
|
|
142
|
-
import * as
|
|
93
|
+
import * as path2 from "path";
|
|
143
94
|
import {
|
|
144
95
|
validateConfig,
|
|
145
96
|
validateInstalled,
|
|
146
97
|
validateSkillsLock,
|
|
147
|
-
|
|
98
|
+
TokensPackLockSchema
|
|
148
99
|
} from "@teamix-evo/registry";
|
|
149
|
-
var
|
|
100
|
+
var TEAMIX_DIR = ".teamix-evo";
|
|
150
101
|
var CONFIG_FILE = "config.json";
|
|
151
102
|
var MANIFEST_FILE = "manifest.json";
|
|
152
|
-
var
|
|
153
|
-
var DESIGN_LOCK_FILE = "pack.lock.json";
|
|
103
|
+
var TOKENS_LOCK_FILE = "tokens-lock.json";
|
|
154
104
|
var SKILLS_DIR = "skills";
|
|
155
105
|
var SKILLS_LOCK_FILE = "manifest.lock.json";
|
|
156
106
|
function getTeamixDir(projectRoot) {
|
|
157
|
-
return
|
|
107
|
+
return path2.join(projectRoot, TEAMIX_DIR);
|
|
158
108
|
}
|
|
159
109
|
async function ensureTeamixDir(projectRoot) {
|
|
160
110
|
const dir = getTeamixDir(projectRoot);
|
|
@@ -162,84 +112,85 @@ async function ensureTeamixDir(projectRoot) {
|
|
|
162
112
|
return dir;
|
|
163
113
|
}
|
|
164
114
|
async function readProjectConfig(projectRoot) {
|
|
165
|
-
const configPath =
|
|
115
|
+
const configPath = path2.join(projectRoot, TEAMIX_DIR, CONFIG_FILE);
|
|
166
116
|
const raw = await readFileOrNull(configPath);
|
|
167
117
|
if (raw === null) return null;
|
|
118
|
+
let data;
|
|
168
119
|
try {
|
|
169
|
-
|
|
170
|
-
const result = validateConfig(data);
|
|
171
|
-
if (!result.success) {
|
|
172
|
-
logger.warn(`Invalid config.json: ${result.error}`);
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
return result.data;
|
|
120
|
+
data = JSON.parse(raw);
|
|
176
121
|
} catch (err) {
|
|
177
|
-
|
|
178
|
-
|
|
122
|
+
throw new Error(
|
|
123
|
+
`Corrupted config.json (${err.message}). Fix the JSON manually or remove the file to start fresh; refusing to clobber prior config.`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
const result = validateConfig(data);
|
|
127
|
+
if (!result.success) {
|
|
128
|
+
throw new Error(
|
|
129
|
+
`Invalid config.json schema: ${result.error}. Fix the file manually or remove it to start fresh.`
|
|
130
|
+
);
|
|
179
131
|
}
|
|
132
|
+
return result.data;
|
|
180
133
|
}
|
|
181
134
|
async function writeProjectConfig(projectRoot, config) {
|
|
182
|
-
const configPath =
|
|
135
|
+
const configPath = path2.join(projectRoot, TEAMIX_DIR, CONFIG_FILE);
|
|
183
136
|
await writeFileSafe(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
184
137
|
logger.debug(`Wrote config \u2192 ${configPath}`);
|
|
185
138
|
}
|
|
186
139
|
async function readInstalledManifest(projectRoot) {
|
|
187
|
-
const manifestPath =
|
|
140
|
+
const manifestPath = path2.join(projectRoot, TEAMIX_DIR, MANIFEST_FILE);
|
|
188
141
|
const raw = await readFileOrNull(manifestPath);
|
|
189
142
|
if (raw === null) return null;
|
|
143
|
+
let data;
|
|
190
144
|
try {
|
|
191
|
-
|
|
192
|
-
const result = validateInstalled(data);
|
|
193
|
-
if (!result.success) {
|
|
194
|
-
logger.warn(`Invalid manifest.json: ${result.error}`);
|
|
195
|
-
return null;
|
|
196
|
-
}
|
|
197
|
-
return result.data;
|
|
145
|
+
data = JSON.parse(raw);
|
|
198
146
|
} catch (err) {
|
|
199
|
-
|
|
200
|
-
|
|
147
|
+
throw new Error(
|
|
148
|
+
`Corrupted manifest.json (${err.message}). Fix the JSON manually or remove the file to start fresh; refusing to clobber prior install records.`
|
|
149
|
+
);
|
|
201
150
|
}
|
|
151
|
+
const result = validateInstalled(data);
|
|
152
|
+
if (!result.success) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`Invalid manifest.json schema: ${result.error}. Fix the file manually or remove it to start fresh.`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
return result.data;
|
|
202
158
|
}
|
|
203
159
|
async function writeInstalledManifest(projectRoot, manifest) {
|
|
204
|
-
const manifestPath =
|
|
160
|
+
const manifestPath = path2.join(projectRoot, TEAMIX_DIR, MANIFEST_FILE);
|
|
205
161
|
await writeFileSafe(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
|
|
206
162
|
logger.debug(`Wrote manifest \u2192 ${manifestPath}`);
|
|
207
163
|
}
|
|
208
|
-
async function
|
|
209
|
-
const lockPath =
|
|
210
|
-
projectRoot,
|
|
211
|
-
TEAMIX_DIR2,
|
|
212
|
-
DESIGN_DIR,
|
|
213
|
-
DESIGN_LOCK_FILE
|
|
214
|
-
);
|
|
164
|
+
async function readTokensLock(projectRoot) {
|
|
165
|
+
const lockPath = path2.join(projectRoot, TEAMIX_DIR, TOKENS_LOCK_FILE);
|
|
215
166
|
const raw = await readFileOrNull(lockPath);
|
|
216
167
|
if (raw === null) return null;
|
|
217
168
|
try {
|
|
218
|
-
const parsed =
|
|
169
|
+
const parsed = TokensPackLockSchema.safeParse(JSON.parse(raw));
|
|
219
170
|
if (!parsed.success) {
|
|
220
|
-
logger.warn(`Invalid
|
|
171
|
+
logger.warn(`Invalid tokens-lock.json: ${parsed.error.message}`);
|
|
221
172
|
return null;
|
|
222
173
|
}
|
|
223
174
|
return parsed.data;
|
|
224
175
|
} catch (err) {
|
|
225
176
|
logger.warn(
|
|
226
|
-
`Failed to parse
|
|
177
|
+
`Failed to parse tokens-lock.json: ${err.message}`
|
|
227
178
|
);
|
|
228
179
|
return null;
|
|
229
180
|
}
|
|
230
181
|
}
|
|
231
|
-
async function
|
|
232
|
-
const lock = await
|
|
182
|
+
async function readTokensVariant(projectRoot) {
|
|
183
|
+
const lock = await readTokensLock(projectRoot);
|
|
233
184
|
return lock?.variant.name ?? null;
|
|
234
185
|
}
|
|
235
186
|
function getSkillsSourceDir(projectRoot, skillName) {
|
|
236
|
-
const base =
|
|
237
|
-
return skillName ?
|
|
187
|
+
const base = path2.join(projectRoot, TEAMIX_DIR, SKILLS_DIR);
|
|
188
|
+
return skillName ? path2.join(base, skillName) : base;
|
|
238
189
|
}
|
|
239
190
|
async function readSkillsLock(projectRoot) {
|
|
240
|
-
const lockPath =
|
|
191
|
+
const lockPath = path2.join(
|
|
241
192
|
projectRoot,
|
|
242
|
-
|
|
193
|
+
TEAMIX_DIR,
|
|
243
194
|
SKILLS_DIR,
|
|
244
195
|
SKILLS_LOCK_FILE
|
|
245
196
|
);
|
|
@@ -261,9 +212,9 @@ async function readSkillsLock(projectRoot) {
|
|
|
261
212
|
}
|
|
262
213
|
}
|
|
263
214
|
async function writeSkillsLock(projectRoot, lock) {
|
|
264
|
-
const lockPath =
|
|
215
|
+
const lockPath = path2.join(
|
|
265
216
|
projectRoot,
|
|
266
|
-
|
|
217
|
+
TEAMIX_DIR,
|
|
267
218
|
SKILLS_DIR,
|
|
268
219
|
SKILLS_LOCK_FILE
|
|
269
220
|
);
|
|
@@ -272,21 +223,21 @@ async function writeSkillsLock(projectRoot, lock) {
|
|
|
272
223
|
}
|
|
273
224
|
|
|
274
225
|
// src/core/skills-client.ts
|
|
275
|
-
import * as
|
|
226
|
+
import * as path3 from "path";
|
|
276
227
|
import * as fs2 from "fs/promises";
|
|
277
228
|
import { createRequire } from "module";
|
|
278
229
|
import { loadSkillsPackageManifest } from "@teamix-evo/registry";
|
|
279
230
|
var require2 = createRequire(import.meta.url);
|
|
280
231
|
function resolvePackageRoot(packageName) {
|
|
281
232
|
const pkgJsonPath = require2.resolve(`${packageName}/package.json`);
|
|
282
|
-
return
|
|
233
|
+
return path3.dirname(pkgJsonPath);
|
|
283
234
|
}
|
|
284
235
|
async function loadSkillsData(packageName) {
|
|
285
236
|
const packageRoot = resolvePackageRoot(packageName);
|
|
286
237
|
logger.debug(`Resolved skills package root: ${packageRoot}`);
|
|
287
238
|
const manifest = await loadSkillsPackageManifest(packageRoot);
|
|
288
239
|
let data = {};
|
|
289
|
-
const dataPath =
|
|
240
|
+
const dataPath = path3.join(packageRoot, "_data.json");
|
|
290
241
|
try {
|
|
291
242
|
const raw = await fs2.readFile(dataPath, "utf-8");
|
|
292
243
|
data = JSON.parse(raw);
|
|
@@ -300,13 +251,13 @@ async function loadSkillsData(packageName) {
|
|
|
300
251
|
}
|
|
301
252
|
|
|
302
253
|
// src/core/skills-installer.ts
|
|
303
|
-
import * as
|
|
254
|
+
import * as path7 from "path";
|
|
304
255
|
import * as fs5 from "fs/promises";
|
|
305
256
|
import { replaceManagedRegion } from "@teamix-evo/registry";
|
|
306
257
|
|
|
307
258
|
// src/ide/QoderAdapter.ts
|
|
308
259
|
import * as os from "os";
|
|
309
|
-
import * as
|
|
260
|
+
import * as path4 from "path";
|
|
310
261
|
var QoderAdapter = class {
|
|
311
262
|
kind = "qoder";
|
|
312
263
|
name = "qoder";
|
|
@@ -317,14 +268,14 @@ var QoderAdapter = class {
|
|
|
317
268
|
return true;
|
|
318
269
|
}
|
|
319
270
|
getSkillTargetDir(skillName, scope, projectRoot) {
|
|
320
|
-
const base = scope === "global" ?
|
|
321
|
-
return
|
|
271
|
+
const base = scope === "global" ? path4.join(os.homedir(), ".qoder") : path4.join(projectRoot ?? this.getProjectRoot(), ".qoder");
|
|
272
|
+
return path4.join(base, "skills", skillName);
|
|
322
273
|
}
|
|
323
274
|
};
|
|
324
275
|
|
|
325
276
|
// src/ide/ClaudeAdapter.ts
|
|
326
277
|
import * as os2 from "os";
|
|
327
|
-
import * as
|
|
278
|
+
import * as path5 from "path";
|
|
328
279
|
var ClaudeAdapter = class {
|
|
329
280
|
kind = "claude";
|
|
330
281
|
name = "claude";
|
|
@@ -335,8 +286,8 @@ var ClaudeAdapter = class {
|
|
|
335
286
|
return Boolean(process.env.CLAUDECODE);
|
|
336
287
|
}
|
|
337
288
|
getSkillTargetDir(skillName, scope, projectRoot) {
|
|
338
|
-
const base = scope === "global" ?
|
|
339
|
-
return
|
|
289
|
+
const base = scope === "global" ? path5.join(os2.homedir(), ".claude") : path5.join(projectRoot ?? this.getProjectRoot(), ".claude");
|
|
290
|
+
return path5.join(base, "skills", skillName);
|
|
340
291
|
}
|
|
341
292
|
};
|
|
342
293
|
|
|
@@ -383,19 +334,19 @@ async function loadTemplateFile(filePath) {
|
|
|
383
334
|
}
|
|
384
335
|
|
|
385
336
|
// src/utils/path.ts
|
|
386
|
-
import * as
|
|
337
|
+
import * as path6 from "path";
|
|
387
338
|
import * as fs4 from "fs/promises";
|
|
388
339
|
function resolveSourcePath(source, variantDir, packageRoot) {
|
|
389
340
|
if (source.startsWith("_template/")) {
|
|
390
|
-
return
|
|
341
|
+
return path6.join(packageRoot, source);
|
|
391
342
|
}
|
|
392
|
-
return
|
|
343
|
+
return path6.join(variantDir, source);
|
|
393
344
|
}
|
|
394
345
|
async function walkDir(dir) {
|
|
395
346
|
const files = [];
|
|
396
347
|
const entries = await fs4.readdir(dir, { withFileTypes: true });
|
|
397
348
|
for (const entry of entries) {
|
|
398
|
-
const fullPath =
|
|
349
|
+
const fullPath = path6.join(dir, entry.name);
|
|
399
350
|
if (entry.isDirectory()) {
|
|
400
351
|
files.push(...await walkDir(fullPath));
|
|
401
352
|
} else if (entry.isFile()) {
|
|
@@ -438,12 +389,12 @@ async function installSkills(options) {
|
|
|
438
389
|
}
|
|
439
390
|
async function writeSkillSource(skill, options) {
|
|
440
391
|
const { data, packageRoot, projectRoot } = options;
|
|
441
|
-
const sourceAbs =
|
|
392
|
+
const sourceAbs = path7.resolve(packageRoot, skill.source);
|
|
442
393
|
const targetDir = getSkillsSourceDir(projectRoot, skill.name);
|
|
443
394
|
const stat2 = await fs5.stat(sourceAbs);
|
|
444
395
|
const records = [];
|
|
445
396
|
if (stat2.isFile()) {
|
|
446
|
-
const targetFile =
|
|
397
|
+
const targetFile = path7.join(targetDir, "SKILL.md");
|
|
447
398
|
const content = await renderSkillContent(sourceAbs, skill, data);
|
|
448
399
|
await writeFileSafe(targetFile, content);
|
|
449
400
|
records.push(makeSourceRecord(skill, targetFile, content));
|
|
@@ -453,14 +404,14 @@ async function writeSkillSource(skill, options) {
|
|
|
453
404
|
await ensureDir(targetDir);
|
|
454
405
|
const entries = await walkDir(sourceAbs);
|
|
455
406
|
for (const entry of entries) {
|
|
456
|
-
const rel2 =
|
|
457
|
-
let targetFile =
|
|
407
|
+
const rel2 = path7.relative(sourceAbs, entry);
|
|
408
|
+
let targetFile = path7.join(targetDir, rel2);
|
|
458
409
|
if (skill.template && targetFile.endsWith(".hbs")) {
|
|
459
410
|
targetFile = targetFile.slice(0, -4);
|
|
460
411
|
}
|
|
461
412
|
const content = skill.template && entry.endsWith(".hbs") ? renderTemplate(await loadTemplateFile(entry), { ...data, skill }) : await fs5.readFile(entry, "utf-8");
|
|
462
413
|
await writeFileSafe(targetFile, content);
|
|
463
|
-
const relWritten =
|
|
414
|
+
const relWritten = path7.relative(targetDir, targetFile);
|
|
464
415
|
records.push(makeSourceRecord(skill, targetFile, content, relWritten));
|
|
465
416
|
logger.debug(` Wrote source: ${targetFile}`);
|
|
466
417
|
}
|
|
@@ -474,11 +425,19 @@ async function mirrorSkillToIde(skill, ide, scope, projectRoot) {
|
|
|
474
425
|
const sourceFiles = await walkDir(sourceDir);
|
|
475
426
|
await ensureDir(targetDir);
|
|
476
427
|
for (const src of sourceFiles) {
|
|
477
|
-
const rel2 =
|
|
478
|
-
const targetFile =
|
|
479
|
-
const
|
|
480
|
-
await
|
|
481
|
-
|
|
428
|
+
const rel2 = path7.relative(sourceDir, src);
|
|
429
|
+
const targetFile = path7.join(targetDir, rel2);
|
|
430
|
+
const sourceContent = await fs5.readFile(src, "utf-8");
|
|
431
|
+
const existing = await readFileOrNull(targetFile);
|
|
432
|
+
if (existing !== null && existing !== sourceContent) {
|
|
433
|
+
logger.warn(
|
|
434
|
+
`Mirror drift detected at ${targetFile} \u2014 overwriting from source. Edit ${src} (not the mirror) and re-run \`teamix-evo skills sync\`.`
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
await writeFileSafe(targetFile, sourceContent);
|
|
438
|
+
records.push(
|
|
439
|
+
makeMirrorRecord(skill, targetFile, sourceContent, ide, scope, rel2)
|
|
440
|
+
);
|
|
482
441
|
logger.debug(` Mirrored ${ide}:${scope}: ${targetFile}`);
|
|
483
442
|
}
|
|
484
443
|
return records;
|
|
@@ -537,7 +496,7 @@ async function updateSkills(options) {
|
|
|
537
496
|
}
|
|
538
497
|
async function rewriteSkillSource(skill, options, summary) {
|
|
539
498
|
const { data, packageRoot, projectRoot } = options;
|
|
540
|
-
const sourceAbs =
|
|
499
|
+
const sourceAbs = path7.resolve(packageRoot, skill.source);
|
|
541
500
|
const targetDir = getSkillsSourceDir(projectRoot, skill.name);
|
|
542
501
|
const stat2 = await fs5.stat(sourceAbs);
|
|
543
502
|
if (!stat2.isFile()) {
|
|
@@ -545,8 +504,8 @@ async function rewriteSkillSource(skill, options, summary) {
|
|
|
545
504
|
const entries = await walkDir(sourceAbs);
|
|
546
505
|
const records = [];
|
|
547
506
|
for (const entry of entries) {
|
|
548
|
-
const rel2 =
|
|
549
|
-
let targetFile2 =
|
|
507
|
+
const rel2 = path7.relative(sourceAbs, entry);
|
|
508
|
+
let targetFile2 = path7.join(targetDir, rel2);
|
|
550
509
|
if (skill.template && targetFile2.endsWith(".hbs")) {
|
|
551
510
|
targetFile2 = targetFile2.slice(0, -4);
|
|
552
511
|
}
|
|
@@ -559,12 +518,12 @@ async function rewriteSkillSource(skill, options, summary) {
|
|
|
559
518
|
summary.created++;
|
|
560
519
|
}
|
|
561
520
|
await writeFileSafe(targetFile2, content);
|
|
562
|
-
const relWritten =
|
|
521
|
+
const relWritten = path7.relative(targetDir, targetFile2);
|
|
563
522
|
records.push(makeSourceRecord(skill, targetFile2, content, relWritten));
|
|
564
523
|
}
|
|
565
524
|
return records;
|
|
566
525
|
}
|
|
567
|
-
const targetFile =
|
|
526
|
+
const targetFile = path7.join(targetDir, "SKILL.md");
|
|
568
527
|
const newContent = await renderSkillContent(sourceAbs, skill, data);
|
|
569
528
|
const exists = await fileExists(targetFile);
|
|
570
529
|
if (skill.updateStrategy === "frozen") {
|
|
@@ -639,14 +598,20 @@ async function syncSkillsToIdes(options) {
|
|
|
639
598
|
await ensureDir(targetDir);
|
|
640
599
|
const sourceFiles = await walkDir(sourceDir);
|
|
641
600
|
for (const src of sourceFiles) {
|
|
642
|
-
const rel2 =
|
|
643
|
-
const targetFile =
|
|
644
|
-
const
|
|
645
|
-
await
|
|
601
|
+
const rel2 = path7.relative(sourceDir, src);
|
|
602
|
+
const targetFile = path7.join(targetDir, rel2);
|
|
603
|
+
const sourceContent = await fs5.readFile(src, "utf-8");
|
|
604
|
+
const existing = await readFileOrNull(targetFile);
|
|
605
|
+
if (existing !== null && existing !== sourceContent) {
|
|
606
|
+
logger.warn(
|
|
607
|
+
`Mirror drift detected at ${targetFile} \u2014 overwriting from source. Edit ${src} (not the mirror) and re-run \`teamix-evo skills sync\`.`
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
await writeFileSafe(targetFile, sourceContent);
|
|
646
611
|
out.push({
|
|
647
612
|
id: rel2 === "SKILL.md" ? skill.id : `${skill.id}:${rel2}`,
|
|
648
613
|
target: targetFile,
|
|
649
|
-
hash: computeHash(
|
|
614
|
+
hash: computeHash(sourceContent),
|
|
650
615
|
strategy: skill.updateStrategy,
|
|
651
616
|
ide,
|
|
652
617
|
scope
|
|
@@ -668,12 +633,18 @@ async function removeSkillFiles(records) {
|
|
|
668
633
|
}
|
|
669
634
|
}
|
|
670
635
|
}
|
|
671
|
-
const
|
|
672
|
-
for (const
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
636
|
+
const startDirs = new Set(records.map((r) => path7.dirname(r.target)));
|
|
637
|
+
for (const startDir of startDirs) {
|
|
638
|
+
let dir = startDir;
|
|
639
|
+
for (let depth = 0; depth < 8; depth++) {
|
|
640
|
+
try {
|
|
641
|
+
const entries = await fs5.readdir(dir);
|
|
642
|
+
if (entries.length !== 0) break;
|
|
643
|
+
await fs5.rmdir(dir);
|
|
644
|
+
} catch {
|
|
645
|
+
break;
|
|
646
|
+
}
|
|
647
|
+
dir = path7.dirname(dir);
|
|
677
648
|
}
|
|
678
649
|
}
|
|
679
650
|
return removed;
|
|
@@ -702,7 +673,7 @@ async function runSkillsAdd(options) {
|
|
|
702
673
|
throw new Error("Scope must be specified (project | global).");
|
|
703
674
|
}
|
|
704
675
|
const { manifest, data, packageRoot } = await loadSkillsData(packageName);
|
|
705
|
-
const
|
|
676
|
+
const currentTokensVariant = await readTokensVariant(projectRoot);
|
|
706
677
|
if (isIncremental) {
|
|
707
678
|
const known = new Set(manifest.skills.map((s) => s.id));
|
|
708
679
|
const unknown = requestedNames.filter((n) => !known.has(n));
|
|
@@ -733,15 +704,15 @@ async function runSkillsAdd(options) {
|
|
|
733
704
|
skippedSkillIds = [];
|
|
734
705
|
onlyIds = manifest.skills.filter((s) => {
|
|
735
706
|
if (!s.variant) return true;
|
|
736
|
-
if (!
|
|
707
|
+
if (!currentTokensVariant) {
|
|
737
708
|
logger.debug(
|
|
738
|
-
`Skipping variant-bound skill "${s.id}" (variant=${s.variant}): no
|
|
709
|
+
`Skipping variant-bound skill "${s.id}" (variant=${s.variant}): no tokens variant installed; will be picked up when "tokens init" runs.`
|
|
739
710
|
);
|
|
740
711
|
return false;
|
|
741
712
|
}
|
|
742
|
-
if (s.variant !==
|
|
713
|
+
if (s.variant !== currentTokensVariant) {
|
|
743
714
|
logger.debug(
|
|
744
|
-
`Skipping variant-bound skill "${s.id}" (variant=${s.variant}): current
|
|
715
|
+
`Skipping variant-bound skill "${s.id}" (variant=${s.variant}): current tokens variant is "${currentTokensVariant}".`
|
|
745
716
|
);
|
|
746
717
|
return false;
|
|
747
718
|
}
|
|
@@ -844,85 +815,108 @@ function mergeInstalledResources(existing, next) {
|
|
|
844
815
|
return [...map.values()];
|
|
845
816
|
}
|
|
846
817
|
|
|
847
|
-
// src/core/
|
|
848
|
-
var BASELINE_DESIGN_RULES_SKILL = "teamix-evo-design-rules";
|
|
818
|
+
// src/core/tokens-init.ts
|
|
849
819
|
var DEFAULT_SKILLS_PACKAGE2 = "@teamix-evo/skills";
|
|
850
820
|
var DEFAULT_AUTO_SKILL_IDES = ["qoder", "claude"];
|
|
851
821
|
var DEFAULT_AUTO_SKILL_SCOPE = "project";
|
|
852
|
-
var
|
|
822
|
+
var DEFAULT_TOKENS_PACKAGE = "@teamix-evo/tokens";
|
|
823
|
+
var CONSUMER_TOKENS_DIR = "tokens";
|
|
824
|
+
var CONSUMER_THEME_FILE = "tokens.theme.css";
|
|
825
|
+
var CONSUMER_OVERRIDES_FILE = "tokens.overrides.css";
|
|
826
|
+
var EMPTY_OVERRIDES_TEMPLATE = `/* User-owned token overrides \u2014 frozen on subsequent installs. */
|
|
827
|
+
/* See @teamix-evo/tokens variant theme.css for available CSS custom properties. */
|
|
828
|
+
`;
|
|
853
829
|
var require3 = createRequire2(import.meta.url);
|
|
854
|
-
async function
|
|
830
|
+
async function runTokensInit(options) {
|
|
855
831
|
const { projectRoot, variant, ide } = options;
|
|
856
|
-
const packageName = options.packageName ??
|
|
832
|
+
const packageName = options.packageName ?? DEFAULT_TOKENS_PACKAGE;
|
|
857
833
|
await ensureTeamixDir(projectRoot);
|
|
858
834
|
const existingConfig = await readProjectConfig(projectRoot);
|
|
859
|
-
if (existingConfig?.packages?.
|
|
835
|
+
if (existingConfig?.packages?.tokens) {
|
|
836
|
+
const existingVariant = existingConfig.packages.tokens.variant;
|
|
837
|
+
if (existingVariant === variant) {
|
|
838
|
+
return { status: "already-initialized", existingVariant };
|
|
839
|
+
}
|
|
860
840
|
return {
|
|
861
|
-
status: "
|
|
862
|
-
existingVariant
|
|
841
|
+
status: "variant-mismatch",
|
|
842
|
+
existingVariant,
|
|
843
|
+
requestedVariant: variant
|
|
863
844
|
};
|
|
864
845
|
}
|
|
865
|
-
const packageRoot = options.packageRoot ??
|
|
866
|
-
const catalog = await
|
|
867
|
-
const variantEntry = catalog
|
|
846
|
+
const packageRoot = options.packageRoot ?? resolveTokensPackageRoot(packageName);
|
|
847
|
+
const catalog = await loadTokensPackageManifest(packageRoot);
|
|
848
|
+
const variantEntry = getVariantEntry(catalog, variant);
|
|
868
849
|
if (!variantEntry) {
|
|
869
850
|
const known = catalog.variants.map((v) => v.name).join(", ");
|
|
870
851
|
throw new Error(
|
|
871
|
-
`
|
|
852
|
+
`Tokens variant not found: "${variant}". Known variants: ${known || "(none)"}. Hint: run "teamix-evo tokens list-variants" to see all.`
|
|
872
853
|
);
|
|
873
854
|
}
|
|
874
|
-
const defaultDir = path9.join(packageRoot, "default");
|
|
875
|
-
const variantDir = path9.join(packageRoot, "variants", variant);
|
|
876
|
-
const defaultPack = await loadDesignPack(defaultDir);
|
|
877
|
-
const variantPack = await loadDesignPack(variantDir);
|
|
878
|
-
const merge = await mergeDefaultAndVariant(defaultDir, variantDir);
|
|
879
855
|
const installed = [];
|
|
880
|
-
for (const
|
|
881
|
-
const result = await
|
|
856
|
+
for (const fileRel of variantEntry.files) {
|
|
857
|
+
const result = await installVariantFile(fileRel, packageRoot, projectRoot);
|
|
882
858
|
if (result) installed.push(result);
|
|
883
859
|
}
|
|
860
|
+
const overridesAbs = path8.join(
|
|
861
|
+
projectRoot,
|
|
862
|
+
CONSUMER_TOKENS_DIR,
|
|
863
|
+
CONSUMER_OVERRIDES_FILE
|
|
864
|
+
);
|
|
865
|
+
if (!await fileExists(overridesAbs)) {
|
|
866
|
+
await writeFileSafe(overridesAbs, EMPTY_OVERRIDES_TEMPLATE);
|
|
867
|
+
}
|
|
868
|
+
const overridesContent = await fs6.readFile(overridesAbs, "utf-8");
|
|
869
|
+
installed.push({
|
|
870
|
+
id: `tokens:${CONSUMER_OVERRIDES_FILE}`,
|
|
871
|
+
target: path8.posix.join(CONSUMER_TOKENS_DIR, CONSUMER_OVERRIDES_FILE),
|
|
872
|
+
hash: computeHash(overridesContent),
|
|
873
|
+
strategy: "frozen"
|
|
874
|
+
});
|
|
884
875
|
const lock = {
|
|
885
876
|
schemaVersion: 1,
|
|
886
|
-
default: { version: defaultPack.version, from: packageName },
|
|
887
877
|
variant: {
|
|
888
|
-
name:
|
|
889
|
-
displayName:
|
|
890
|
-
version:
|
|
878
|
+
name: variantEntry.name,
|
|
879
|
+
displayName: variantEntry.displayName,
|
|
880
|
+
version: variantEntry.version,
|
|
891
881
|
from: packageName
|
|
892
882
|
},
|
|
893
|
-
|
|
883
|
+
packageVersion: catalog.version,
|
|
884
|
+
linked: variantEntry.linked,
|
|
894
885
|
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
895
886
|
};
|
|
896
887
|
await writeFileSafe(
|
|
897
|
-
|
|
888
|
+
path8.join(projectRoot, ".teamix-evo", "tokens-lock.json"),
|
|
898
889
|
JSON.stringify(lock, null, 2) + "\n"
|
|
899
890
|
);
|
|
900
891
|
const config = {
|
|
901
892
|
$schema: "https://teamix-evo.dev/schema/config/v1.json",
|
|
902
893
|
schemaVersion: 1,
|
|
903
|
-
ide,
|
|
894
|
+
ide: existingConfig?.ide ?? ide,
|
|
904
895
|
packages: {
|
|
905
|
-
|
|
896
|
+
...existingConfig?.packages ?? {},
|
|
897
|
+
tokens: {
|
|
906
898
|
variant,
|
|
907
|
-
version:
|
|
899
|
+
version: variantEntry.version,
|
|
908
900
|
tailwind: "v4"
|
|
909
901
|
}
|
|
910
902
|
}
|
|
911
903
|
};
|
|
912
904
|
await writeProjectConfig(projectRoot, config);
|
|
913
|
-
const
|
|
905
|
+
const prior = await readInstalledManifest(projectRoot) ?? {
|
|
914
906
|
schemaVersion: 1,
|
|
915
|
-
installed: [
|
|
916
|
-
{
|
|
917
|
-
package: packageName,
|
|
918
|
-
variant,
|
|
919
|
-
version: variantPack.version,
|
|
920
|
-
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
921
|
-
resources: installed
|
|
922
|
-
}
|
|
923
|
-
]
|
|
907
|
+
installed: []
|
|
924
908
|
};
|
|
925
|
-
|
|
909
|
+
const tokensIdx = prior.installed.findIndex((p) => p.package === packageName);
|
|
910
|
+
const tokensEntry = {
|
|
911
|
+
package: packageName,
|
|
912
|
+
variant,
|
|
913
|
+
version: variantEntry.version,
|
|
914
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
915
|
+
resources: installed
|
|
916
|
+
};
|
|
917
|
+
if (tokensIdx >= 0) prior.installed[tokensIdx] = tokensEntry;
|
|
918
|
+
else prior.installed.push(tokensEntry);
|
|
919
|
+
await writeInstalledManifest(projectRoot, prior);
|
|
926
920
|
const skills = await tryAutoInstallVariantSkills({
|
|
927
921
|
projectRoot,
|
|
928
922
|
variant,
|
|
@@ -932,21 +926,16 @@ async function runDesignInit(options) {
|
|
|
932
926
|
status: "installed",
|
|
933
927
|
packageName,
|
|
934
928
|
variant,
|
|
935
|
-
version:
|
|
929
|
+
version: variantEntry.version,
|
|
936
930
|
count: installed.length,
|
|
937
931
|
resources: installed,
|
|
938
|
-
merge: {
|
|
939
|
-
overrides: merge.overrides,
|
|
940
|
-
variantAdds: merge.variantAdds,
|
|
941
|
-
defaultPassThrough: merge.defaultPassThrough
|
|
942
|
-
},
|
|
943
932
|
skills
|
|
944
933
|
};
|
|
945
934
|
}
|
|
946
935
|
async function tryAutoInstallVariantSkills(args) {
|
|
947
936
|
const { projectRoot, variant, ide } = args;
|
|
948
|
-
const variantSkillId =
|
|
949
|
-
const desired = [
|
|
937
|
+
const variantSkillId = `teamix-evo-design-${variant}`;
|
|
938
|
+
const desired = [variantSkillId];
|
|
950
939
|
let manifestSkillIds;
|
|
951
940
|
try {
|
|
952
941
|
const { manifest } = await loadSkillsData(DEFAULT_SKILLS_PACKAGE2);
|
|
@@ -966,7 +955,9 @@ async function tryAutoInstallVariantSkills(args) {
|
|
|
966
955
|
const missing = desired.filter((id) => !manifestSkillIds.has(id));
|
|
967
956
|
if (missing.length > 0) {
|
|
968
957
|
logger.warn(
|
|
969
|
-
`Skills auto-install: not found in manifest, skipping: ${missing.join(
|
|
958
|
+
`Skills auto-install: not found in manifest, skipping: ${missing.join(
|
|
959
|
+
", "
|
|
960
|
+
)}.`
|
|
970
961
|
);
|
|
971
962
|
}
|
|
972
963
|
if (present.length === 0) {
|
|
@@ -1011,34 +1002,100 @@ async function tryAutoInstallVariantSkills(args) {
|
|
|
1011
1002
|
};
|
|
1012
1003
|
}
|
|
1013
1004
|
}
|
|
1014
|
-
async function
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1005
|
+
async function installVariantFile(fileRelToPackage, packageRoot, projectRoot) {
|
|
1006
|
+
const sourceAbs = path8.join(packageRoot, fileRelToPackage);
|
|
1007
|
+
const base = path8.basename(fileRelToPackage);
|
|
1008
|
+
if (base === "theme.css") {
|
|
1009
|
+
const targetRel = path8.posix.join(
|
|
1010
|
+
CONSUMER_TOKENS_DIR,
|
|
1011
|
+
CONSUMER_THEME_FILE
|
|
1012
|
+
);
|
|
1013
|
+
const targetAbs = path8.join(projectRoot, targetRel);
|
|
1014
|
+
const content = await fs6.readFile(sourceAbs, "utf-8");
|
|
1015
|
+
await writeFileSafe(targetAbs, content);
|
|
1020
1016
|
return {
|
|
1021
|
-
id: `
|
|
1022
|
-
target:
|
|
1023
|
-
hash: computeHash(
|
|
1024
|
-
strategy:
|
|
1017
|
+
id: `tokens:${CONSUMER_THEME_FILE}`,
|
|
1018
|
+
target: targetRel,
|
|
1019
|
+
hash: computeHash(content),
|
|
1020
|
+
strategy: "regenerable"
|
|
1025
1021
|
};
|
|
1026
1022
|
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1023
|
+
if (base === "overrides.css" || base === "tokens.overrides.css") {
|
|
1024
|
+
const targetRel = path8.posix.join(
|
|
1025
|
+
CONSUMER_TOKENS_DIR,
|
|
1026
|
+
CONSUMER_OVERRIDES_FILE
|
|
1027
|
+
);
|
|
1028
|
+
const targetAbs = path8.join(projectRoot, targetRel);
|
|
1029
|
+
if (await fileExists(targetAbs)) {
|
|
1030
|
+
const existing = await fs6.readFile(targetAbs, "utf-8");
|
|
1031
|
+
return {
|
|
1032
|
+
id: `tokens:${CONSUMER_OVERRIDES_FILE}`,
|
|
1033
|
+
target: targetRel,
|
|
1034
|
+
hash: computeHash(existing),
|
|
1035
|
+
strategy: "frozen"
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
const content = await fs6.readFile(sourceAbs, "utf-8");
|
|
1039
|
+
await writeFileSafe(targetAbs, content);
|
|
1040
|
+
return {
|
|
1041
|
+
id: `tokens:${CONSUMER_OVERRIDES_FILE}`,
|
|
1042
|
+
target: targetRel,
|
|
1043
|
+
hash: computeHash(content),
|
|
1044
|
+
strategy: "frozen"
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
return null;
|
|
1035
1048
|
}
|
|
1036
|
-
function
|
|
1049
|
+
function resolveTokensPackageRoot(packageName) {
|
|
1037
1050
|
const pkgJson = require3.resolve(`${packageName}/package.json`);
|
|
1038
|
-
return
|
|
1051
|
+
return path8.dirname(pkgJson);
|
|
1052
|
+
}
|
|
1053
|
+
async function listTokenVariants(packageName = DEFAULT_TOKENS_PACKAGE, packageRoot) {
|
|
1054
|
+
const root = packageRoot ?? resolveTokensPackageRoot(packageName);
|
|
1055
|
+
const catalog = await loadTokensPackageManifest(root);
|
|
1056
|
+
return {
|
|
1057
|
+
packageName,
|
|
1058
|
+
packageVersion: catalog.version,
|
|
1059
|
+
variants: catalog.variants.map((v) => ({
|
|
1060
|
+
name: v.name,
|
|
1061
|
+
displayName: v.displayName,
|
|
1062
|
+
version: v.version,
|
|
1063
|
+
description: v.description,
|
|
1064
|
+
linked: v.linked
|
|
1065
|
+
}))
|
|
1066
|
+
};
|
|
1039
1067
|
}
|
|
1040
1068
|
|
|
1041
1069
|
// src/core/ui-init.ts
|
|
1070
|
+
import * as fs7 from "fs/promises";
|
|
1071
|
+
import { createRequire as createRequire3 } from "module";
|
|
1072
|
+
import * as path9 from "path";
|
|
1073
|
+
var require4 = createRequire3(import.meta.url);
|
|
1074
|
+
async function deployPreferencesCss(projectRoot) {
|
|
1075
|
+
const targetDir = path9.join(projectRoot, "src");
|
|
1076
|
+
const targetPath = path9.join(targetDir, "preferences.css");
|
|
1077
|
+
try {
|
|
1078
|
+
await fs7.access(targetPath);
|
|
1079
|
+
logger.debug(`preferences.css already exists at ${targetPath}, skipping`);
|
|
1080
|
+
return "skipped";
|
|
1081
|
+
} catch {
|
|
1082
|
+
}
|
|
1083
|
+
let sourcePath;
|
|
1084
|
+
try {
|
|
1085
|
+
const uiPkgJson = require4.resolve("@teamix-evo/ui/package.json");
|
|
1086
|
+
sourcePath = path9.join(path9.dirname(uiPkgJson), "src", "preferences.css");
|
|
1087
|
+
await fs7.access(sourcePath);
|
|
1088
|
+
} catch {
|
|
1089
|
+
logger.debug(
|
|
1090
|
+
"Could not resolve @teamix-evo/ui/src/preferences.css; skipping deploy"
|
|
1091
|
+
);
|
|
1092
|
+
return "source-missing";
|
|
1093
|
+
}
|
|
1094
|
+
await fs7.mkdir(targetDir, { recursive: true });
|
|
1095
|
+
const content = await fs7.readFile(sourcePath, "utf-8");
|
|
1096
|
+
await fs7.writeFile(targetPath, content, "utf-8");
|
|
1097
|
+
return "deployed";
|
|
1098
|
+
}
|
|
1042
1099
|
var DEFAULT_UI_ALIASES = {
|
|
1043
1100
|
components: "src/components/ui",
|
|
1044
1101
|
hooks: "src/hooks",
|
|
@@ -1082,23 +1139,25 @@ async function runUiInit(options) {
|
|
|
1082
1139
|
rsc
|
|
1083
1140
|
};
|
|
1084
1141
|
await writeProjectConfig(projectRoot, config);
|
|
1142
|
+
const preferencesCss = await deployPreferencesCss(projectRoot);
|
|
1085
1143
|
return {
|
|
1086
1144
|
status: "installed",
|
|
1087
1145
|
aliases,
|
|
1088
1146
|
iconLibrary,
|
|
1089
1147
|
tsx,
|
|
1090
|
-
rsc
|
|
1148
|
+
rsc,
|
|
1149
|
+
preferencesCss
|
|
1091
1150
|
};
|
|
1092
1151
|
}
|
|
1093
1152
|
|
|
1094
1153
|
// src/core/ui-client.ts
|
|
1095
1154
|
import * as path10 from "path";
|
|
1096
|
-
import * as
|
|
1097
|
-
import { createRequire as
|
|
1155
|
+
import * as fs8 from "fs/promises";
|
|
1156
|
+
import { createRequire as createRequire4 } from "module";
|
|
1098
1157
|
import { loadUiPackageManifest } from "@teamix-evo/registry";
|
|
1099
|
-
var
|
|
1158
|
+
var require5 = createRequire4(import.meta.url);
|
|
1100
1159
|
function resolvePackageRoot2(packageName) {
|
|
1101
|
-
const pkgJsonPath =
|
|
1160
|
+
const pkgJsonPath = require5.resolve(`${packageName}/package.json`);
|
|
1102
1161
|
return path10.dirname(pkgJsonPath);
|
|
1103
1162
|
}
|
|
1104
1163
|
async function loadUiData(packageName) {
|
|
@@ -1108,7 +1167,7 @@ async function loadUiData(packageName) {
|
|
|
1108
1167
|
let data = {};
|
|
1109
1168
|
const dataPath = path10.join(packageRoot, "_data.json");
|
|
1110
1169
|
try {
|
|
1111
|
-
const raw = await
|
|
1170
|
+
const raw = await fs8.readFile(dataPath, "utf-8");
|
|
1112
1171
|
data = JSON.parse(raw);
|
|
1113
1172
|
} catch (err) {
|
|
1114
1173
|
if (err.code !== "ENOENT") {
|
|
@@ -1121,7 +1180,7 @@ async function loadUiData(packageName) {
|
|
|
1121
1180
|
|
|
1122
1181
|
// src/core/ui-installer.ts
|
|
1123
1182
|
import * as path11 from "path";
|
|
1124
|
-
import * as
|
|
1183
|
+
import * as fs9 from "fs/promises";
|
|
1125
1184
|
import { resolveUiEntryOrder } from "@teamix-evo/registry";
|
|
1126
1185
|
|
|
1127
1186
|
// src/utils/transform-imports.ts
|
|
@@ -1161,12 +1220,12 @@ function aliasToImportPath(alias) {
|
|
|
1161
1220
|
}
|
|
1162
1221
|
|
|
1163
1222
|
// src/core/ui-installer.ts
|
|
1164
|
-
var DESIGN_COMPONENTS_DIR = ".teamix-evo/design/components";
|
|
1165
1223
|
async function installUiEntries(options) {
|
|
1166
1224
|
const {
|
|
1167
1225
|
projectRoot,
|
|
1168
1226
|
manifest,
|
|
1169
1227
|
packageRoot,
|
|
1228
|
+
entryPackageRoot,
|
|
1170
1229
|
aliases,
|
|
1171
1230
|
requested,
|
|
1172
1231
|
skipExisting = true
|
|
@@ -1175,7 +1234,6 @@ async function installUiEntries(options) {
|
|
|
1175
1234
|
const idToEntry = new Map(manifest.entries.map((e) => [e.id, e]));
|
|
1176
1235
|
const resources = [];
|
|
1177
1236
|
const npmDeps = {};
|
|
1178
|
-
const metaFiles = [];
|
|
1179
1237
|
let written = 0;
|
|
1180
1238
|
let skipped = 0;
|
|
1181
1239
|
for (const id of orderedIds) {
|
|
@@ -1194,8 +1252,9 @@ async function installUiEntries(options) {
|
|
|
1194
1252
|
skipped++;
|
|
1195
1253
|
continue;
|
|
1196
1254
|
}
|
|
1197
|
-
const
|
|
1198
|
-
const
|
|
1255
|
+
const rootForEntry = entryPackageRoot?.get(entry.id) ?? packageRoot;
|
|
1256
|
+
const sourceAbs = path11.resolve(rootForEntry, file.source);
|
|
1257
|
+
const raw = await fs9.readFile(sourceAbs, "utf-8");
|
|
1199
1258
|
const transformed = rewriteImports(raw, aliases);
|
|
1200
1259
|
await writeFileSafe(targetAbs, transformed);
|
|
1201
1260
|
written++;
|
|
@@ -1207,32 +1266,13 @@ async function installUiEntries(options) {
|
|
|
1207
1266
|
strategy: entry.updateStrategy ?? "frozen"
|
|
1208
1267
|
});
|
|
1209
1268
|
}
|
|
1210
|
-
if (entry.meta) {
|
|
1211
|
-
const metaSourceAbs = path11.resolve(packageRoot, entry.meta);
|
|
1212
|
-
const metaContent = await fs8.readFile(metaSourceAbs, "utf-8");
|
|
1213
|
-
const metaTargetAbs = path11.join(
|
|
1214
|
-
projectRoot,
|
|
1215
|
-
DESIGN_COMPONENTS_DIR,
|
|
1216
|
-
`${entry.id}.meta.md`
|
|
1217
|
-
);
|
|
1218
|
-
await writeFileSafe(metaTargetAbs, metaContent);
|
|
1219
|
-
metaFiles.push(metaTargetAbs);
|
|
1220
|
-
resources.push({
|
|
1221
|
-
id: `${entry.id}:meta`,
|
|
1222
|
-
target: metaTargetAbs,
|
|
1223
|
-
hash: computeHash(metaContent),
|
|
1224
|
-
strategy: "regenerable"
|
|
1225
|
-
});
|
|
1226
|
-
logger.info(` meta: ${rel(projectRoot, metaTargetAbs)}`);
|
|
1227
|
-
}
|
|
1228
1269
|
}
|
|
1229
1270
|
return {
|
|
1230
1271
|
orderedIds,
|
|
1231
1272
|
resources,
|
|
1232
1273
|
npmDependencies: npmDeps,
|
|
1233
1274
|
written,
|
|
1234
|
-
skipped
|
|
1235
|
-
metaFiles
|
|
1275
|
+
skipped
|
|
1236
1276
|
};
|
|
1237
1277
|
}
|
|
1238
1278
|
function resolveTargetPath(projectRoot, aliases, entry, file) {
|
|
@@ -1251,7 +1291,7 @@ async function removeUiFiles(records) {
|
|
|
1251
1291
|
const removed = [];
|
|
1252
1292
|
for (const r of records) {
|
|
1253
1293
|
try {
|
|
1254
|
-
await
|
|
1294
|
+
await fs9.unlink(r.target);
|
|
1255
1295
|
removed.push(r.target);
|
|
1256
1296
|
} catch (err) {
|
|
1257
1297
|
if (err.code !== "ENOENT") {
|
|
@@ -1262,8 +1302,8 @@ async function removeUiFiles(records) {
|
|
|
1262
1302
|
const parents = new Set(records.map((r) => path11.dirname(r.target)));
|
|
1263
1303
|
for (const dir of parents) {
|
|
1264
1304
|
try {
|
|
1265
|
-
const entries = await
|
|
1266
|
-
if (entries.length === 0) await
|
|
1305
|
+
const entries = await fs9.readdir(dir);
|
|
1306
|
+
if (entries.length === 0) await fs9.rmdir(dir);
|
|
1267
1307
|
} catch {
|
|
1268
1308
|
}
|
|
1269
1309
|
}
|
|
@@ -1329,7 +1369,6 @@ async function runUiAdd(options) {
|
|
|
1329
1369
|
orderedIds: result.orderedIds,
|
|
1330
1370
|
written: result.written,
|
|
1331
1371
|
skipped: result.skipped,
|
|
1332
|
-
metaFiles: result.metaFiles,
|
|
1333
1372
|
npmDependencies: result.npmDependencies,
|
|
1334
1373
|
resources: result.resources
|
|
1335
1374
|
};
|
|
@@ -1372,7 +1411,7 @@ async function runUiList(options) {
|
|
|
1372
1411
|
|
|
1373
1412
|
// src/core/installer.ts
|
|
1374
1413
|
import * as path12 from "path";
|
|
1375
|
-
import * as
|
|
1414
|
+
import * as fs10 from "fs/promises";
|
|
1376
1415
|
async function installResources(options) {
|
|
1377
1416
|
const { projectRoot, manifest, data, variantDir, packageRoot } = options;
|
|
1378
1417
|
const installedResources = [];
|
|
@@ -1415,7 +1454,7 @@ async function installSingleResource(resource, projectRoot, data, variantDir, pa
|
|
|
1415
1454
|
const templateContent = await loadTemplateFile(sourcePath);
|
|
1416
1455
|
content = renderTemplate(templateContent, data);
|
|
1417
1456
|
} else {
|
|
1418
|
-
content = await
|
|
1457
|
+
content = await fs10.readFile(sourcePath, "utf-8");
|
|
1419
1458
|
}
|
|
1420
1459
|
await writeFileSafe(targetPath, content);
|
|
1421
1460
|
const hash = computeHash(content);
|
|
@@ -1448,7 +1487,7 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
1448
1487
|
const templateContent = await loadTemplateFile(entry);
|
|
1449
1488
|
content = renderTemplate(templateContent, data);
|
|
1450
1489
|
} else {
|
|
1451
|
-
content = await
|
|
1490
|
+
content = await fs10.readFile(entry, "utf-8");
|
|
1452
1491
|
}
|
|
1453
1492
|
await writeFileSafe(targetFile, content);
|
|
1454
1493
|
const hash = computeHash(content);
|
|
@@ -1466,12 +1505,12 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
|
|
|
1466
1505
|
|
|
1467
1506
|
// src/core/registry-client.ts
|
|
1468
1507
|
import * as path13 from "path";
|
|
1469
|
-
import * as
|
|
1470
|
-
import { createRequire as
|
|
1508
|
+
import * as fs11 from "fs/promises";
|
|
1509
|
+
import { createRequire as createRequire5 } from "module";
|
|
1471
1510
|
import { loadVariantManifest } from "@teamix-evo/registry";
|
|
1472
|
-
var
|
|
1511
|
+
var require6 = createRequire5(import.meta.url);
|
|
1473
1512
|
function resolvePackageRoot3(packageName) {
|
|
1474
|
-
const pkgJsonPath =
|
|
1513
|
+
const pkgJsonPath = require6.resolve(`${packageName}/package.json`);
|
|
1475
1514
|
return path13.dirname(pkgJsonPath);
|
|
1476
1515
|
}
|
|
1477
1516
|
async function loadVariantData(packageName, variant) {
|
|
@@ -1483,7 +1522,7 @@ async function loadVariantData(packageName, variant) {
|
|
|
1483
1522
|
let data = {};
|
|
1484
1523
|
const dataPath = path13.join(variantDir, "_data.json");
|
|
1485
1524
|
try {
|
|
1486
|
-
const raw = await
|
|
1525
|
+
const raw = await fs11.readFile(dataPath, "utf-8");
|
|
1487
1526
|
data = JSON.parse(raw);
|
|
1488
1527
|
} catch (err) {
|
|
1489
1528
|
if (err.code !== "ENOENT") {
|
|
@@ -1501,6 +1540,7 @@ export {
|
|
|
1501
1540
|
installResources,
|
|
1502
1541
|
installSkills,
|
|
1503
1542
|
installUiEntries,
|
|
1543
|
+
listTokenVariants,
|
|
1504
1544
|
loadSkillsData,
|
|
1505
1545
|
loadUiData,
|
|
1506
1546
|
loadVariantData,
|
|
@@ -1508,8 +1548,8 @@ export {
|
|
|
1508
1548
|
readProjectConfig,
|
|
1509
1549
|
removeSkillFiles,
|
|
1510
1550
|
removeUiFiles,
|
|
1511
|
-
runDesignInit,
|
|
1512
1551
|
runSkillsAdd,
|
|
1552
|
+
runTokensInit,
|
|
1513
1553
|
runUiAdd,
|
|
1514
1554
|
runUiInit,
|
|
1515
1555
|
runUiList,
|