teamix-evo 0.20.1 → 0.20.3
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 -1
- package/dist/core/index.js +236 -4
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +276 -8
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -5411,6 +5411,7 @@ async function loadUiData(packageName) {
|
|
|
5411
5411
|
init_fs();
|
|
5412
5412
|
import * as path25 from "path";
|
|
5413
5413
|
import * as fs20 from "fs/promises";
|
|
5414
|
+
import { isBuiltin } from "module";
|
|
5414
5415
|
import { resolveUiEntryOrder } from "@teamix-evo/registry";
|
|
5415
5416
|
|
|
5416
5417
|
// src/utils/transform-imports.ts
|
|
@@ -5466,6 +5467,12 @@ async function installUiEntries(options) {
|
|
|
5466
5467
|
} = options;
|
|
5467
5468
|
const orderedIds = resolveUiEntryOrder(manifest.entries, requested);
|
|
5468
5469
|
const idToEntry = new Map(manifest.entries.map((e) => [e.id, e]));
|
|
5470
|
+
const sourceContents = await preflightUiEntrySources({
|
|
5471
|
+
manifest,
|
|
5472
|
+
orderedIds,
|
|
5473
|
+
packageRoot,
|
|
5474
|
+
entryPackageRoot
|
|
5475
|
+
});
|
|
5469
5476
|
const resources = [];
|
|
5470
5477
|
const npmDeps = {};
|
|
5471
5478
|
let created = 0;
|
|
@@ -5494,7 +5501,12 @@ async function installUiEntries(options) {
|
|
|
5494
5501
|
}
|
|
5495
5502
|
const rootForEntry = entryPackageRoot?.get(entry.id) ?? packageRoot;
|
|
5496
5503
|
const sourceAbs = path25.resolve(rootForEntry, file.source);
|
|
5497
|
-
const raw =
|
|
5504
|
+
const raw = sourceContents.get(sourceAbs);
|
|
5505
|
+
if (raw === void 0) {
|
|
5506
|
+
throw new Error(
|
|
5507
|
+
`UI install preflight did not load source file "${file.source}" for entry "${entry.id}". No files were written.`
|
|
5508
|
+
);
|
|
5509
|
+
}
|
|
5498
5510
|
const transformed = rewriteImports(raw, aliases, { flatten });
|
|
5499
5511
|
if (exists) {
|
|
5500
5512
|
const current = await fs20.readFile(targetAbs, "utf-8");
|
|
@@ -5547,6 +5559,189 @@ async function installUiEntries(options) {
|
|
|
5547
5559
|
skipped
|
|
5548
5560
|
};
|
|
5549
5561
|
}
|
|
5562
|
+
var PROJECT_RUNTIME_PACKAGES = /* @__PURE__ */ new Set(["react", "react-dom"]);
|
|
5563
|
+
async function preflightUiEntrySources(options) {
|
|
5564
|
+
const { manifest, orderedIds, packageRoot, entryPackageRoot } = options;
|
|
5565
|
+
const sourceContents = /* @__PURE__ */ new Map();
|
|
5566
|
+
const aliasProviders = buildSourceAliasProviders(manifest.entries);
|
|
5567
|
+
const sourceProviders = buildRelativeSourceProviders(
|
|
5568
|
+
manifest.entries,
|
|
5569
|
+
packageRoot,
|
|
5570
|
+
entryPackageRoot
|
|
5571
|
+
);
|
|
5572
|
+
const issues = [];
|
|
5573
|
+
for (const id of orderedIds) {
|
|
5574
|
+
const entry = manifest.entries.find((candidate) => candidate.id === id);
|
|
5575
|
+
if (!entry) continue;
|
|
5576
|
+
const declaredRegistry = new Set(entry.registryDependencies ?? []);
|
|
5577
|
+
const declaredPackages = new Set(Object.keys(entry.dependencies ?? {}));
|
|
5578
|
+
const rootForEntry = entryPackageRoot?.get(entry.id) ?? packageRoot;
|
|
5579
|
+
for (const file of entry.files) {
|
|
5580
|
+
const sourceAbs = path25.resolve(rootForEntry, file.source);
|
|
5581
|
+
const source = await fs20.readFile(sourceAbs, "utf-8");
|
|
5582
|
+
sourceContents.set(sourceAbs, source);
|
|
5583
|
+
if (manifest.package !== "ui") continue;
|
|
5584
|
+
for (const specifier of extractModuleSpecifiers(source)) {
|
|
5585
|
+
if (specifier.startsWith("@/")) {
|
|
5586
|
+
const provider = aliasProviders.get(specifier);
|
|
5587
|
+
if (!provider) {
|
|
5588
|
+
issues.push({
|
|
5589
|
+
entryId: entry.id,
|
|
5590
|
+
source: file.source,
|
|
5591
|
+
message: `unresolved registry import "${specifier}"`
|
|
5592
|
+
});
|
|
5593
|
+
} else if (provider !== entry.id && !declaredRegistry.has(provider)) {
|
|
5594
|
+
issues.push({
|
|
5595
|
+
entryId: entry.id,
|
|
5596
|
+
source: file.source,
|
|
5597
|
+
message: `undeclared registry dependency "${provider}" (import "${specifier}")`
|
|
5598
|
+
});
|
|
5599
|
+
}
|
|
5600
|
+
continue;
|
|
5601
|
+
}
|
|
5602
|
+
if (specifier.startsWith(".")) {
|
|
5603
|
+
const provider = resolveRelativeProvider(
|
|
5604
|
+
path25.resolve(path25.dirname(sourceAbs), specifier),
|
|
5605
|
+
sourceProviders
|
|
5606
|
+
);
|
|
5607
|
+
if (!provider) {
|
|
5608
|
+
issues.push({
|
|
5609
|
+
entryId: entry.id,
|
|
5610
|
+
source: file.source,
|
|
5611
|
+
message: `unshipped or unresolved relative import "${specifier}"`
|
|
5612
|
+
});
|
|
5613
|
+
} else if (provider !== entry.id && !declaredRegistry.has(provider)) {
|
|
5614
|
+
issues.push({
|
|
5615
|
+
entryId: entry.id,
|
|
5616
|
+
source: file.source,
|
|
5617
|
+
message: `undeclared registry dependency "${provider}" (relative import "${specifier}")`
|
|
5618
|
+
});
|
|
5619
|
+
}
|
|
5620
|
+
continue;
|
|
5621
|
+
}
|
|
5622
|
+
const packageName = externalPackageName(specifier);
|
|
5623
|
+
if (!isBuiltin(specifier) && !PROJECT_RUNTIME_PACKAGES.has(packageName) && !declaredPackages.has(packageName)) {
|
|
5624
|
+
issues.push({
|
|
5625
|
+
entryId: entry.id,
|
|
5626
|
+
source: file.source,
|
|
5627
|
+
message: `undeclared npm dependency "${packageName}" (import "${specifier}")`
|
|
5628
|
+
});
|
|
5629
|
+
}
|
|
5630
|
+
}
|
|
5631
|
+
}
|
|
5632
|
+
}
|
|
5633
|
+
if (issues.length > 0) {
|
|
5634
|
+
const details = issues.sort(
|
|
5635
|
+
(a, b) => `${a.entryId}:${a.source}:${a.message}`.localeCompare(
|
|
5636
|
+
`${b.entryId}:${b.source}:${b.message}`
|
|
5637
|
+
)
|
|
5638
|
+
).map(
|
|
5639
|
+
(issue) => `- Entry "${issue.entryId}" (${issue.source}): ${issue.message}`
|
|
5640
|
+
).join("\n");
|
|
5641
|
+
throw new Error(
|
|
5642
|
+
[
|
|
5643
|
+
"UI install preflight failed. No files were written.",
|
|
5644
|
+
details,
|
|
5645
|
+
"Fix registryDependencies/dependencies in the package manifest, publish the corrected package, and retry."
|
|
5646
|
+
].join("\n")
|
|
5647
|
+
);
|
|
5648
|
+
}
|
|
5649
|
+
return sourceContents;
|
|
5650
|
+
}
|
|
5651
|
+
function extractModuleSpecifiers(source) {
|
|
5652
|
+
const specifiers = /* @__PURE__ */ new Set();
|
|
5653
|
+
const staticPattern = /\b(?:import|export)\s+(?:type\s+)?(?:[^'";]*?\s+from\s+)?(['"])([^'"]+)\1/g;
|
|
5654
|
+
const dynamicPattern = /\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g;
|
|
5655
|
+
for (const pattern of [staticPattern, dynamicPattern]) {
|
|
5656
|
+
let match;
|
|
5657
|
+
while ((match = pattern.exec(source)) !== null) {
|
|
5658
|
+
if (match[2]) specifiers.add(match[2]);
|
|
5659
|
+
}
|
|
5660
|
+
}
|
|
5661
|
+
return specifiers;
|
|
5662
|
+
}
|
|
5663
|
+
function buildSourceAliasProviders(entries) {
|
|
5664
|
+
const providers = /* @__PURE__ */ new Map();
|
|
5665
|
+
for (const entry of entries) {
|
|
5666
|
+
for (const file of entry.files) {
|
|
5667
|
+
const target = stripModuleExtension(file.targetName);
|
|
5668
|
+
const aliases = sourceAliases(file.targetAlias, target);
|
|
5669
|
+
for (const alias of aliases) {
|
|
5670
|
+
const current = providers.get(alias);
|
|
5671
|
+
if (current && current !== entry.id) {
|
|
5672
|
+
throw new Error(
|
|
5673
|
+
`UI install preflight found ambiguous source alias "${alias}" for entries "${current}" and "${entry.id}". No files were written.`
|
|
5674
|
+
);
|
|
5675
|
+
}
|
|
5676
|
+
providers.set(alias, entry.id);
|
|
5677
|
+
}
|
|
5678
|
+
}
|
|
5679
|
+
}
|
|
5680
|
+
return providers;
|
|
5681
|
+
}
|
|
5682
|
+
function sourceAliases(targetAlias, target) {
|
|
5683
|
+
switch (targetAlias) {
|
|
5684
|
+
case "components":
|
|
5685
|
+
return [`@/components/${target}`, `@/components/ui/${target}`];
|
|
5686
|
+
case "business":
|
|
5687
|
+
return [
|
|
5688
|
+
`@/components/business/${target}`,
|
|
5689
|
+
`@/business/${target}`
|
|
5690
|
+
];
|
|
5691
|
+
case "hooks":
|
|
5692
|
+
return [`@/hooks/${target}`];
|
|
5693
|
+
case "utils":
|
|
5694
|
+
return [`@/utils/${target}`, `@/lib/utils/${target}`];
|
|
5695
|
+
case "lib":
|
|
5696
|
+
return [`@/lib/${target}`];
|
|
5697
|
+
case "blocks":
|
|
5698
|
+
return [`@/blocks/${target}`];
|
|
5699
|
+
default:
|
|
5700
|
+
return [];
|
|
5701
|
+
}
|
|
5702
|
+
}
|
|
5703
|
+
function buildRelativeSourceProviders(entries, packageRoot, entryPackageRoot) {
|
|
5704
|
+
const providers = /* @__PURE__ */ new Map();
|
|
5705
|
+
for (const entry of entries) {
|
|
5706
|
+
const rootForEntry = entryPackageRoot?.get(entry.id) ?? packageRoot;
|
|
5707
|
+
for (const file of entry.files) {
|
|
5708
|
+
const absolute = path25.resolve(rootForEntry, file.source);
|
|
5709
|
+
for (const candidate of relativeSourceCandidates(absolute)) {
|
|
5710
|
+
providers.set(candidate, entry.id);
|
|
5711
|
+
}
|
|
5712
|
+
}
|
|
5713
|
+
}
|
|
5714
|
+
return providers;
|
|
5715
|
+
}
|
|
5716
|
+
function resolveRelativeProvider(absolute, providers) {
|
|
5717
|
+
for (const candidate of relativeSourceCandidates(absolute)) {
|
|
5718
|
+
const provider = providers.get(candidate);
|
|
5719
|
+
if (provider) return provider;
|
|
5720
|
+
}
|
|
5721
|
+
return void 0;
|
|
5722
|
+
}
|
|
5723
|
+
function relativeSourceCandidates(absolute) {
|
|
5724
|
+
const extension = path25.extname(absolute);
|
|
5725
|
+
if (extension) return [absolute];
|
|
5726
|
+
return [
|
|
5727
|
+
absolute,
|
|
5728
|
+
`${absolute}.ts`,
|
|
5729
|
+
`${absolute}.tsx`,
|
|
5730
|
+
`${absolute}.js`,
|
|
5731
|
+
`${absolute}.jsx`,
|
|
5732
|
+
path25.join(absolute, "index.ts"),
|
|
5733
|
+
path25.join(absolute, "index.tsx"),
|
|
5734
|
+
path25.join(absolute, "index.js"),
|
|
5735
|
+
path25.join(absolute, "index.jsx")
|
|
5736
|
+
];
|
|
5737
|
+
}
|
|
5738
|
+
function stripModuleExtension(value) {
|
|
5739
|
+
return value.replace(/\.(?:[cm]?[jt]sx?)$/, "");
|
|
5740
|
+
}
|
|
5741
|
+
function externalPackageName(specifier) {
|
|
5742
|
+
const parts = specifier.split("/");
|
|
5743
|
+
return specifier.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0] ?? specifier;
|
|
5744
|
+
}
|
|
5550
5745
|
function resolveTargetPath(projectRoot, aliases, entry, file) {
|
|
5551
5746
|
const aliasDir = aliases[file.targetAlias];
|
|
5552
5747
|
if (!aliasDir) {
|
|
@@ -8356,7 +8551,16 @@ init_logger();
|
|
|
8356
8551
|
import * as path35 from "path";
|
|
8357
8552
|
import * as fs29 from "fs";
|
|
8358
8553
|
import { execa } from "execa";
|
|
8359
|
-
|
|
8554
|
+
function renderEslintConfig(tailwindCssConfigPath) {
|
|
8555
|
+
const tailwindSettings = tailwindCssConfigPath ? `
|
|
8556
|
+
{
|
|
8557
|
+
settings: {
|
|
8558
|
+
tailwindcss: {
|
|
8559
|
+
cssConfigPath: '${tailwindCssConfigPath}',
|
|
8560
|
+
},
|
|
8561
|
+
},
|
|
8562
|
+
},` : "";
|
|
8563
|
+
return `/**
|
|
8360
8564
|
* teamix-evo consumer ESLint preset \u2014 9 token-discipline rules.
|
|
8361
8565
|
* - Repo-wide: no-color-literal / no-arbitrary-tw-value / no-raw-color-scale /
|
|
8362
8566
|
* no-large-radius / prefer-gap-over-space / no-manual-dark-classnames /
|
|
@@ -8367,8 +8571,30 @@ var ESLINT_CONFIG_CONTENT = `/**
|
|
|
8367
8571
|
*/
|
|
8368
8572
|
import consumerPreset from '@teamix-evo/eslint-config/presets/consumer';
|
|
8369
8573
|
|
|
8370
|
-
export default [
|
|
8574
|
+
export default [
|
|
8575
|
+
...consumerPreset,${tailwindSettings}
|
|
8576
|
+
];
|
|
8371
8577
|
`;
|
|
8578
|
+
}
|
|
8579
|
+
var TAILWIND_CSS_CANDIDATES = [
|
|
8580
|
+
"src/index.css",
|
|
8581
|
+
"src/globals.css",
|
|
8582
|
+
"src/app/globals.css",
|
|
8583
|
+
"app/globals.css",
|
|
8584
|
+
"styles/globals.css",
|
|
8585
|
+
"src/styles/tailwind.css"
|
|
8586
|
+
];
|
|
8587
|
+
async function detectTailwindCssConfigPath(projectRoot) {
|
|
8588
|
+
for (const candidate of TAILWIND_CSS_CANDIDATES) {
|
|
8589
|
+
const content = await readFileOrNull(path35.join(projectRoot, candidate));
|
|
8590
|
+
if (content && /@(?:import\s+['"]tailwindcss(?:\/[^'"]*)?['"]|theme\b|tailwind\b)/.test(
|
|
8591
|
+
content
|
|
8592
|
+
)) {
|
|
8593
|
+
return `./${candidate}`;
|
|
8594
|
+
}
|
|
8595
|
+
}
|
|
8596
|
+
return null;
|
|
8597
|
+
}
|
|
8372
8598
|
var STYLELINT_CONFIG_CONTENT = `/** @type {import('stylelint').Config} */
|
|
8373
8599
|
module.exports = {
|
|
8374
8600
|
extends: ['@teamix-evo/stylelint-config/presets/consumer'],
|
|
@@ -8433,7 +8659,13 @@ async function runLintInit(options) {
|
|
|
8433
8659
|
let wroteEslint = false;
|
|
8434
8660
|
let wroteStylelint = false;
|
|
8435
8661
|
if (eslintNeedsWrite) {
|
|
8436
|
-
await
|
|
8662
|
+
const tailwindCssConfigPath = await detectTailwindCssConfigPath(
|
|
8663
|
+
projectRoot
|
|
8664
|
+
);
|
|
8665
|
+
await writeFileSafe(
|
|
8666
|
+
eslintConfigPath,
|
|
8667
|
+
renderEslintConfig(tailwindCssConfigPath)
|
|
8668
|
+
);
|
|
8437
8669
|
logger.debug(`Wrote eslint.config.js \u2192 ${eslintConfigPath}`);
|
|
8438
8670
|
wroteEslint = true;
|
|
8439
8671
|
}
|
|
@@ -8575,6 +8807,7 @@ lintCommand.addCommand(initCommand4);
|
|
|
8575
8807
|
// src/commands/init/index.ts
|
|
8576
8808
|
import { Command as Command36 } from "commander";
|
|
8577
8809
|
import * as path39 from "path";
|
|
8810
|
+
import { realpath } from "fs/promises";
|
|
8578
8811
|
import { execa as execa2 } from "execa";
|
|
8579
8812
|
|
|
8580
8813
|
// src/core/project-state.ts
|
|
@@ -9493,7 +9726,7 @@ var initCommand5 = new Command36("init").description("\u521D\u59CB\u5316 Teamix
|
|
|
9493
9726
|
variant: answers.variant,
|
|
9494
9727
|
ides: answers.ides,
|
|
9495
9728
|
force: opts.force,
|
|
9496
|
-
skipInstall:
|
|
9729
|
+
skipInstall: shouldSkipInstall(opts.install),
|
|
9497
9730
|
dryRun,
|
|
9498
9731
|
onStep: (step) => {
|
|
9499
9732
|
const icon = STEP_ICON[step.status];
|
|
@@ -9533,7 +9766,9 @@ var initCommand5 = new Command36("init").description("\u521D\u59CB\u5316 Teamix
|
|
|
9533
9766
|
}
|
|
9534
9767
|
}
|
|
9535
9768
|
if (result.status === "installed") {
|
|
9536
|
-
|
|
9769
|
+
if (shouldAutoCommitAfterInit(state.state, opts.git)) {
|
|
9770
|
+
await autoCommitAfterInit(cwd);
|
|
9771
|
+
}
|
|
9537
9772
|
logger.info("");
|
|
9538
9773
|
logger.info("Next steps:");
|
|
9539
9774
|
logger.info(" \u2022 \u542F\u52A8 dev server \u9A8C\u8BC1\uFF1A`npm run dev`");
|
|
@@ -9596,12 +9831,30 @@ async function runScaffoldPhase(cwd, variant, opts) {
|
|
|
9596
9831
|
}
|
|
9597
9832
|
logger.info("");
|
|
9598
9833
|
}
|
|
9834
|
+
function shouldAutoCommitAfterInit(initialState, gitEnabled) {
|
|
9835
|
+
return initialState === "empty" && gitEnabled !== false;
|
|
9836
|
+
}
|
|
9837
|
+
function shouldSkipInstall(install) {
|
|
9838
|
+
return install === false;
|
|
9839
|
+
}
|
|
9599
9840
|
async function autoCommitAfterInit(cwd) {
|
|
9841
|
+
let gitTopLevel;
|
|
9842
|
+
let canonicalCwd;
|
|
9600
9843
|
try {
|
|
9601
|
-
await execa2("git", ["rev-parse", "--
|
|
9844
|
+
const result = await execa2("git", ["rev-parse", "--show-toplevel"], { cwd });
|
|
9845
|
+
[gitTopLevel, canonicalCwd] = await Promise.all([
|
|
9846
|
+
realpath(result.stdout.trim()),
|
|
9847
|
+
realpath(cwd)
|
|
9848
|
+
]);
|
|
9602
9849
|
} catch {
|
|
9603
9850
|
return;
|
|
9604
9851
|
}
|
|
9852
|
+
if (gitTopLevel !== canonicalCwd) {
|
|
9853
|
+
logger.warn(
|
|
9854
|
+
"\u8DF3\u8FC7\u81EA\u52A8\u63D0\u4EA4\uFF1A\u76EE\u6807\u76EE\u5F55\u4E0D\u662F\u72EC\u7ACB Git \u4ED3\u5E93\uFF0C\u907F\u514D\u8BEF\u63D0\u4EA4\u7236\u4ED3\u5E93\u5185\u5BB9\u3002"
|
|
9855
|
+
);
|
|
9856
|
+
return;
|
|
9857
|
+
}
|
|
9605
9858
|
try {
|
|
9606
9859
|
await execa2("git", ["add", "."], { cwd });
|
|
9607
9860
|
await execa2(
|
|
@@ -9609,8 +9862,23 @@ async function autoCommitAfterInit(cwd) {
|
|
|
9609
9862
|
["commit", "-m", "chore: init teamix-evo", "--allow-empty"],
|
|
9610
9863
|
{ cwd }
|
|
9611
9864
|
);
|
|
9865
|
+
const { stdout: worktreeStatus } = await execa2(
|
|
9866
|
+
"git",
|
|
9867
|
+
["status", "--porcelain", "--untracked-files=all"],
|
|
9868
|
+
{ cwd }
|
|
9869
|
+
);
|
|
9612
9870
|
logger.info("");
|
|
9613
|
-
|
|
9871
|
+
if (worktreeStatus.trim()) {
|
|
9872
|
+
logger.warn("init \u5DF2\u81EA\u52A8\u63D0\u4EA4\uFF0C\u4F46\u5DE5\u4F5C\u533A\u4ECD\u6709\u672A\u63D0\u4EA4\u5185\u5BB9\uFF1A");
|
|
9873
|
+
for (const line of worktreeStatus.trim().split("\n")) {
|
|
9874
|
+
logger.warn(` ${line}`);
|
|
9875
|
+
}
|
|
9876
|
+
logger.warn("\u8BF7\u5904\u7406\u4E0A\u8FF0\u6587\u4EF6\u540E\u518D\u6B21\u786E\u8BA4 `git status --short` \u4E3A\u7A7A\u3002");
|
|
9877
|
+
} else {
|
|
9878
|
+
logger.success(
|
|
9879
|
+
"\u5DF2\u81EA\u52A8\u63D0\u4EA4 init \u4EA7\u7269\uFF1Achore: init teamix-evo\uFF08\u5DE5\u4F5C\u533A\u5E72\u51C0\uFF09"
|
|
9880
|
+
);
|
|
9881
|
+
}
|
|
9614
9882
|
} catch (err) {
|
|
9615
9883
|
logger.warn(
|
|
9616
9884
|
`\u81EA\u52A8\u63D0\u4EA4\u5931\u8D25\uFF08\u975E\u5173\u952E\uFF09\uFF1A${err instanceof Error ? err.message : String(err)}`
|