elcrm 1.1.20 → 1.1.22
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/dist/index.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/index.ts
|
|
5
|
-
import { readFileSync as
|
|
6
|
-
import { dirname as dirname4, join as
|
|
5
|
+
import { readFileSync as readFileSync28 } from "fs";
|
|
6
|
+
import { dirname as dirname4, join as join25 } from "path";
|
|
7
7
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8
8
|
|
|
9
9
|
// src/parseArgs.ts
|
|
@@ -3671,11 +3671,11 @@ async function cmdMigrate(parsed) {
|
|
|
3671
3671
|
}
|
|
3672
3672
|
|
|
3673
3673
|
// src/commands/doctor.ts
|
|
3674
|
-
import { resolve as
|
|
3674
|
+
import { resolve as resolve10 } from "path";
|
|
3675
3675
|
|
|
3676
3676
|
// src/lib/kit/doctor-kit.ts
|
|
3677
|
-
import { existsSync as
|
|
3678
|
-
import { join as
|
|
3677
|
+
import { existsSync as existsSync15 } from "fs";
|
|
3678
|
+
import { join as join17, resolve as resolve7 } from "path";
|
|
3679
3679
|
|
|
3680
3680
|
// src/lib/projectKind.ts
|
|
3681
3681
|
function detectProjectKind(cwd) {
|
|
@@ -3706,8 +3706,37 @@ function isElcrmLibPackage(cwd) {
|
|
|
3706
3706
|
}
|
|
3707
3707
|
|
|
3708
3708
|
// src/lib/kit/paths.ts
|
|
3709
|
-
import { existsSync as
|
|
3709
|
+
import { existsSync as existsSync13, readFileSync as readFileSync20 } from "fs";
|
|
3710
|
+
import { join as join13, resolve as resolve4 } from "path";
|
|
3711
|
+
|
|
3712
|
+
// src/lib/kit/config.ts
|
|
3713
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync2, readFileSync as readFileSync19, writeFileSync as writeFileSync6 } from "fs";
|
|
3714
|
+
import { homedir } from "os";
|
|
3710
3715
|
import { join as join12, resolve as resolve3 } from "path";
|
|
3716
|
+
var FILE = "kit-paths.json";
|
|
3717
|
+
function globalConfigPath() {
|
|
3718
|
+
return join12(homedir(), ".elcrm", FILE);
|
|
3719
|
+
}
|
|
3720
|
+
function localConfigPath(cwd) {
|
|
3721
|
+
return join12(resolve3(cwd), ".elcrm", FILE);
|
|
3722
|
+
}
|
|
3723
|
+
function readJson(path) {
|
|
3724
|
+
if (!existsSync12(path))
|
|
3725
|
+
return {};
|
|
3726
|
+
try {
|
|
3727
|
+
return JSON.parse(readFileSync19(path, "utf8"));
|
|
3728
|
+
} catch {
|
|
3729
|
+
return {};
|
|
3730
|
+
}
|
|
3731
|
+
}
|
|
3732
|
+
function loadKitPathsConfig(cwd) {
|
|
3733
|
+
const global = readJson(globalConfigPath());
|
|
3734
|
+
const local = readJson(localConfigPath(cwd));
|
|
3735
|
+
return {
|
|
3736
|
+
apiDir: local.apiDir || global.apiDir,
|
|
3737
|
+
webDir: local.webDir || global.webDir
|
|
3738
|
+
};
|
|
3739
|
+
}
|
|
3711
3740
|
function readName(dir) {
|
|
3712
3741
|
try {
|
|
3713
3742
|
const j = JSON.parse(readFileSync19(join12(dir, "package.json"), "utf8"));
|
|
@@ -3716,36 +3745,109 @@ function readName(dir) {
|
|
|
3716
3745
|
return null;
|
|
3717
3746
|
}
|
|
3718
3747
|
}
|
|
3719
|
-
function
|
|
3748
|
+
function validateApiDir(dir) {
|
|
3749
|
+
const p = resolve3(dir);
|
|
3750
|
+
if (!existsSync12(join12(p, "src/kit/catalog.ts")))
|
|
3751
|
+
return null;
|
|
3752
|
+
return p;
|
|
3753
|
+
}
|
|
3754
|
+
function validateWebDir(dir) {
|
|
3755
|
+
const p = resolve3(dir);
|
|
3756
|
+
if (readName(p) !== "elui-web")
|
|
3757
|
+
return null;
|
|
3758
|
+
return p;
|
|
3759
|
+
}
|
|
3760
|
+
function saveKitPathsConfig(cwd, patch, global = false) {
|
|
3761
|
+
const path = global ? globalConfigPath() : localConfigPath(cwd);
|
|
3762
|
+
const prev = readJson(path);
|
|
3763
|
+
const next = { ...prev, ...patch };
|
|
3764
|
+
if (next.apiDir) {
|
|
3765
|
+
const ok = validateApiDir(next.apiDir);
|
|
3766
|
+
if (!ok)
|
|
3767
|
+
throw new Error("apiDir: \u043D\u0443\u0436\u0435\u043D \u043A\u0430\u0442\u0430\u043B\u043E\u0433 elUI.api (src/kit/catalog.ts)");
|
|
3768
|
+
next.apiDir = ok;
|
|
3769
|
+
}
|
|
3770
|
+
if (next.webDir) {
|
|
3771
|
+
const ok = validateWebDir(next.webDir);
|
|
3772
|
+
if (!ok)
|
|
3773
|
+
throw new Error("webDir: \u043D\u0443\u0436\u0435\u043D \u043A\u0430\u0442\u0430\u043B\u043E\u0433 elUI.web (package name elui-web)");
|
|
3774
|
+
next.webDir = ok;
|
|
3775
|
+
}
|
|
3776
|
+
mkdirSync2(join12(path, ".."), { recursive: true });
|
|
3777
|
+
writeFileSync6(path, JSON.stringify(next, null, 2) + `
|
|
3778
|
+
`, "utf8");
|
|
3779
|
+
return next;
|
|
3780
|
+
}
|
|
3781
|
+
function persistKitPathsFromOpts(opts) {
|
|
3782
|
+
if (opts.dry)
|
|
3783
|
+
return;
|
|
3784
|
+
const patch = {};
|
|
3785
|
+
if (opts.apiDir?.trim())
|
|
3786
|
+
patch.apiDir = opts.apiDir.trim();
|
|
3787
|
+
if (opts.webDir?.trim())
|
|
3788
|
+
patch.webDir = opts.webDir.trim();
|
|
3789
|
+
if (!patch.apiDir && !patch.webDir)
|
|
3790
|
+
return;
|
|
3791
|
+
saveKitPathsConfig(opts.cwd, patch, opts.global ?? true);
|
|
3792
|
+
}
|
|
3793
|
+
|
|
3794
|
+
// src/lib/kit/paths.ts
|
|
3795
|
+
function readName2(dir) {
|
|
3796
|
+
try {
|
|
3797
|
+
const j = JSON.parse(readFileSync20(join13(dir, "package.json"), "utf8"));
|
|
3798
|
+
return j.name ?? null;
|
|
3799
|
+
} catch {
|
|
3800
|
+
return null;
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
function findEluiApiDir(from, override) {
|
|
3804
|
+
if (override?.trim()) {
|
|
3805
|
+
const p = resolve4(override.trim());
|
|
3806
|
+
if (existsSync13(join13(p, "src/kit/catalog.ts")))
|
|
3807
|
+
return p;
|
|
3808
|
+
return null;
|
|
3809
|
+
}
|
|
3720
3810
|
const env = process.env.ELUI_API_DIR?.trim();
|
|
3721
|
-
if (env &&
|
|
3722
|
-
return
|
|
3723
|
-
|
|
3811
|
+
if (env && existsSync13(join13(env, "src/kit/catalog.ts")))
|
|
3812
|
+
return resolve4(env);
|
|
3813
|
+
const saved = loadKitPathsConfig(from).apiDir;
|
|
3814
|
+
if (saved && existsSync13(join13(saved, "src/kit/catalog.ts")))
|
|
3815
|
+
return resolve4(saved);
|
|
3816
|
+
let dir = resolve4(from);
|
|
3724
3817
|
for (let i = 0;i < 8; i++) {
|
|
3725
3818
|
for (const name of ["elUI.api", "ui-kit.api"]) {
|
|
3726
|
-
const candidate =
|
|
3727
|
-
if (
|
|
3819
|
+
const candidate = join13(dir, name);
|
|
3820
|
+
if (existsSync13(join13(candidate, "src/kit/catalog.ts")))
|
|
3728
3821
|
return candidate;
|
|
3729
3822
|
}
|
|
3730
|
-
const parent =
|
|
3823
|
+
const parent = join13(dir, "..");
|
|
3731
3824
|
if (parent === dir)
|
|
3732
3825
|
break;
|
|
3733
3826
|
dir = parent;
|
|
3734
3827
|
}
|
|
3735
3828
|
return null;
|
|
3736
3829
|
}
|
|
3737
|
-
function findEluiWebDir(from) {
|
|
3830
|
+
function findEluiWebDir(from, override) {
|
|
3831
|
+
if (override?.trim()) {
|
|
3832
|
+
const p = resolve4(override.trim());
|
|
3833
|
+
if (readName2(p) === "elui-web")
|
|
3834
|
+
return p;
|
|
3835
|
+
return null;
|
|
3836
|
+
}
|
|
3738
3837
|
const env = process.env.ELUI_WEB_DIR?.trim();
|
|
3739
|
-
if (env &&
|
|
3740
|
-
return
|
|
3741
|
-
|
|
3838
|
+
if (env && readName2(env) === "elui-web")
|
|
3839
|
+
return resolve4(env);
|
|
3840
|
+
const saved = loadKitPathsConfig(from).webDir;
|
|
3841
|
+
if (saved && readName2(saved) === "elui-web")
|
|
3842
|
+
return resolve4(saved);
|
|
3843
|
+
let dir = resolve4(from);
|
|
3742
3844
|
for (let i = 0;i < 8; i++) {
|
|
3743
3845
|
for (const name of ["elUI.web", "Uikit.web"]) {
|
|
3744
|
-
const candidate =
|
|
3745
|
-
if (
|
|
3846
|
+
const candidate = join13(dir, name);
|
|
3847
|
+
if (readName2(candidate) === "elui-web")
|
|
3746
3848
|
return candidate;
|
|
3747
3849
|
}
|
|
3748
|
-
dir =
|
|
3850
|
+
dir = join13(dir, "..");
|
|
3749
3851
|
}
|
|
3750
3852
|
return null;
|
|
3751
3853
|
}
|
|
@@ -3761,17 +3863,17 @@ function manifestFileName(npmName) {
|
|
|
3761
3863
|
}
|
|
3762
3864
|
|
|
3763
3865
|
// src/lib/kit/sync.ts
|
|
3764
|
-
import { existsSync as
|
|
3765
|
-
import { join as
|
|
3866
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync4, readFileSync as readFileSync23, writeFileSync as writeFileSync8 } from "fs";
|
|
3867
|
+
import { join as join16, resolve as resolve6 } from "path";
|
|
3766
3868
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
3767
3869
|
|
|
3768
3870
|
// src/lib/kit/emit.ts
|
|
3769
|
-
import { mkdirSync as
|
|
3770
|
-
import { join as
|
|
3871
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync22, writeFileSync as writeFileSync7 } from "fs";
|
|
3872
|
+
import { join as join15, resolve as resolve5 } from "path";
|
|
3771
3873
|
|
|
3772
3874
|
// src/lib/kit/parse-dts.ts
|
|
3773
|
-
import { readFileSync as
|
|
3774
|
-
import { basename, join as
|
|
3875
|
+
import { readFileSync as readFileSync21, readdirSync as readdirSync8, statSync as statSync8 } from "fs";
|
|
3876
|
+
import { basename, join as join14 } from "path";
|
|
3775
3877
|
var SKIP_SLUGS = new Set([
|
|
3776
3878
|
"index",
|
|
3777
3879
|
"types",
|
|
@@ -3797,16 +3899,23 @@ function isMainComponentDoc(doc) {
|
|
|
3797
3899
|
return false;
|
|
3798
3900
|
return doc.length > 72;
|
|
3799
3901
|
}
|
|
3800
|
-
function
|
|
3902
|
+
function componentDocs(content, slug) {
|
|
3801
3903
|
const fnAnchor = "export declare function " + slug;
|
|
3802
3904
|
const propsAnchor = "export type " + slug + "Props";
|
|
3803
3905
|
const fnDoc = leadingDoc(content, fnAnchor);
|
|
3804
3906
|
const propsDoc = leadingDoc(content, propsAnchor);
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
if (
|
|
3808
|
-
|
|
3809
|
-
|
|
3907
|
+
const examplesDoc = fnDoc.includes("@example") ? fnDoc : propsDoc.includes("@example") ? propsDoc : fnDoc || propsDoc;
|
|
3908
|
+
let descriptionDoc = fnDoc || propsDoc;
|
|
3909
|
+
if (propsDoc.includes("@example")) {
|
|
3910
|
+
descriptionDoc = propsDoc;
|
|
3911
|
+
} else if (isMainComponentDoc(propsDoc) && propsDoc.length > fnDoc.length) {
|
|
3912
|
+
descriptionDoc = propsDoc;
|
|
3913
|
+
} else if (isMainComponentDoc(fnDoc)) {
|
|
3914
|
+
descriptionDoc = fnDoc;
|
|
3915
|
+
} else if (isMainComponentDoc(propsDoc)) {
|
|
3916
|
+
descriptionDoc = propsDoc;
|
|
3917
|
+
}
|
|
3918
|
+
return { descriptionDoc, examplesDoc };
|
|
3810
3919
|
}
|
|
3811
3920
|
function leadingDoc(content, anchor) {
|
|
3812
3921
|
const idx = content.indexOf(anchor);
|
|
@@ -3874,15 +3983,15 @@ function parseComponentDts(content, slug) {
|
|
|
3874
3983
|
if (!new RegExp("export declare function " + slug + "\\b").test(content)) {
|
|
3875
3984
|
return null;
|
|
3876
3985
|
}
|
|
3877
|
-
const
|
|
3986
|
+
const { descriptionDoc, examplesDoc } = componentDocs(content, slug);
|
|
3878
3987
|
const propsMatch = content.match(new RegExp("export type " + slug + "Props\\s*=\\s*([\\s\\S]*?);\\s*(?:export|$)"));
|
|
3879
3988
|
const propsBlock = propsMatch?.[1] ?? "";
|
|
3880
3989
|
return {
|
|
3881
3990
|
slug,
|
|
3882
3991
|
title: slug,
|
|
3883
|
-
description: descriptionFromDoc(
|
|
3992
|
+
description: descriptionFromDoc(descriptionDoc) || slug,
|
|
3884
3993
|
importFrom: "@elcrm/components",
|
|
3885
|
-
examples: examplesFromDoc(
|
|
3994
|
+
examples: examplesFromDoc(examplesDoc),
|
|
3886
3995
|
props: propsFromPropsBlock(propsBlock)
|
|
3887
3996
|
};
|
|
3888
3997
|
}
|
|
@@ -3894,10 +4003,10 @@ function scanDistComponents(distDir, importFrom) {
|
|
|
3894
4003
|
const slug = basename(name, ".d.ts");
|
|
3895
4004
|
if (SKIP_SLUGS.has(slug) || slug.includes("."))
|
|
3896
4005
|
continue;
|
|
3897
|
-
const path =
|
|
4006
|
+
const path = join14(distDir, name);
|
|
3898
4007
|
if (!statSync8(path).isFile())
|
|
3899
4008
|
continue;
|
|
3900
|
-
const content =
|
|
4009
|
+
const content = readFileSync21(path, "utf8");
|
|
3901
4010
|
const parsed = parseComponentDts(content, slug);
|
|
3902
4011
|
if (!parsed)
|
|
3903
4012
|
continue;
|
|
@@ -3910,7 +4019,7 @@ function scanDistComponents(distDir, importFrom) {
|
|
|
3910
4019
|
|
|
3911
4020
|
// src/lib/kit/emit.ts
|
|
3912
4021
|
function readPkg(cwd) {
|
|
3913
|
-
const j = JSON.parse(
|
|
4022
|
+
const j = JSON.parse(readFileSync22(join15(cwd, "package.json"), "utf8"));
|
|
3914
4023
|
if (!j.name?.startsWith("@elcrm/")) {
|
|
3915
4024
|
throw new Error("elcrm kit emit \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0432 npm-\u043F\u0430\u043A\u0435\u0442\u0435 @elcrm/*");
|
|
3916
4025
|
}
|
|
@@ -3922,7 +4031,7 @@ function emitKitManifest(cwd) {
|
|
|
3922
4031
|
if (!pkgSlug) {
|
|
3923
4032
|
throw new Error(`elcrm kit emit \u2014 \u043F\u0430\u043A\u0435\u0442 ${pkg.name} \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F (\u043D\u0443\u0436\u0435\u043D components|form)`);
|
|
3924
4033
|
}
|
|
3925
|
-
const distDir =
|
|
4034
|
+
const distDir = join15(cwd, "dist");
|
|
3926
4035
|
const components = scanDistComponents(distDir, pkg.name).map((c2) => ({
|
|
3927
4036
|
...c2,
|
|
3928
4037
|
importFrom: pkg.name
|
|
@@ -3939,8 +4048,8 @@ function emitKitManifest(cwd) {
|
|
|
3939
4048
|
function writeKitManifest(cwd, manifest, dry = false) {
|
|
3940
4049
|
const written = [];
|
|
3941
4050
|
const targets = [
|
|
3942
|
-
|
|
3943
|
-
|
|
4051
|
+
join15(cwd, ".elcrm", "kit-manifest.json"),
|
|
4052
|
+
join15(cwd, "dist", "kit-manifest.json")
|
|
3944
4053
|
];
|
|
3945
4054
|
const body = `${JSON.stringify(manifest, null, 2)}
|
|
3946
4055
|
`;
|
|
@@ -3949,20 +4058,20 @@ function writeKitManifest(cwd, manifest, dry = false) {
|
|
|
3949
4058
|
written.push(path);
|
|
3950
4059
|
continue;
|
|
3951
4060
|
}
|
|
3952
|
-
|
|
3953
|
-
|
|
4061
|
+
mkdirSync3(join15(path, ".."), { recursive: true });
|
|
4062
|
+
writeFileSync7(path, body, "utf8");
|
|
3954
4063
|
written.push(path);
|
|
3955
4064
|
}
|
|
3956
4065
|
return written;
|
|
3957
4066
|
}
|
|
3958
4067
|
function readKitManifest(path) {
|
|
3959
|
-
return JSON.parse(
|
|
4068
|
+
return JSON.parse(readFileSync22(resolve5(path), "utf8"));
|
|
3960
4069
|
}
|
|
3961
4070
|
|
|
3962
4071
|
// src/lib/kit/sync.ts
|
|
3963
4072
|
function patchPkgVersions(apiDir, npmName, version, dry) {
|
|
3964
|
-
const path =
|
|
3965
|
-
let src =
|
|
4073
|
+
const path = join16(apiDir, "src/kit/pkg-versions.ts");
|
|
4074
|
+
let src = readFileSync23(path, "utf8");
|
|
3966
4075
|
const re = new RegExp(`("${npmName.replace("/", "\\/")}"\\s*:\\s*")[^"]+(")`);
|
|
3967
4076
|
if (!re.test(src)) {
|
|
3968
4077
|
console.warn(c.yellow(` ! FALLBACK_DEPS: \u043D\u0435\u0442 ${npmName} \u0432 pkg-versions.ts`));
|
|
@@ -3972,17 +4081,17 @@ function patchPkgVersions(apiDir, npmName, version, dry) {
|
|
|
3972
4081
|
if (next === src)
|
|
3973
4082
|
return;
|
|
3974
4083
|
if (!dry)
|
|
3975
|
-
|
|
4084
|
+
writeFileSync8(path, next, "utf8");
|
|
3976
4085
|
console.log(` ${dry ? "~" : c.green("+")} pkg-versions \u2192 ${npmName} ${version}`);
|
|
3977
4086
|
}
|
|
3978
4087
|
function patchWebDep(webDir, npmName, version, dry) {
|
|
3979
|
-
const path =
|
|
3980
|
-
const j = JSON.parse(
|
|
4088
|
+
const path = join16(webDir, "package.json");
|
|
4089
|
+
const j = JSON.parse(readFileSync23(path, "utf8"));
|
|
3981
4090
|
if (!j.dependencies?.[npmName])
|
|
3982
4091
|
return;
|
|
3983
4092
|
j.dependencies[npmName] = version;
|
|
3984
4093
|
if (!dry)
|
|
3985
|
-
|
|
4094
|
+
writeFileSync8(path, `${JSON.stringify(j, null, 2)}
|
|
3986
4095
|
`, "utf8");
|
|
3987
4096
|
console.log(` ${dry ? "~" : c.green("+")} elUI.web \u2192 ${npmName}@${version}`);
|
|
3988
4097
|
}
|
|
@@ -4003,31 +4112,37 @@ function runReseed(apiDir, webDir, dry) {
|
|
|
4003
4112
|
throw new Error("kit:reseed \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0441\u044F \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439");
|
|
4004
4113
|
}
|
|
4005
4114
|
async function syncKitManifest(opts) {
|
|
4006
|
-
const cwd =
|
|
4115
|
+
const cwd = resolve6(opts.cwd);
|
|
4007
4116
|
const dry = opts.dry ?? false;
|
|
4008
4117
|
const reseed = opts.reseed !== false;
|
|
4118
|
+
persistKitPathsFromOpts({
|
|
4119
|
+
cwd,
|
|
4120
|
+
apiDir: opts.apiDir,
|
|
4121
|
+
webDir: opts.webDir,
|
|
4122
|
+
dry
|
|
4123
|
+
});
|
|
4009
4124
|
let manifest;
|
|
4010
4125
|
if (opts.manifestPath) {
|
|
4011
4126
|
manifest = readKitManifest(opts.manifestPath);
|
|
4012
|
-
} else if (
|
|
4013
|
-
manifest = readKitManifest(
|
|
4127
|
+
} else if (existsSync14(join16(cwd, ".elcrm", "kit-manifest.json"))) {
|
|
4128
|
+
manifest = readKitManifest(join16(cwd, ".elcrm", "kit-manifest.json"));
|
|
4014
4129
|
} else {
|
|
4015
4130
|
manifest = emitKitManifest(cwd);
|
|
4016
4131
|
}
|
|
4017
|
-
const apiDir =
|
|
4132
|
+
const apiDir = findEluiApiDir(cwd, opts.apiDir);
|
|
4018
4133
|
if (!apiDir) {
|
|
4019
|
-
throw new Error("\u041D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D elUI.api (
|
|
4134
|
+
throw new Error("\u041D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D elUI.api (elcrm kit config --api=\u2026 --global \u0438\u043B\u0438 ELUI_API_DIR). Manifest: elcrm kit emit");
|
|
4020
4135
|
}
|
|
4021
|
-
const outDir =
|
|
4022
|
-
const outFile =
|
|
4136
|
+
const outDir = join16(apiDir, "src/kit/manifests");
|
|
4137
|
+
const outFile = join16(outDir, manifestFileName(manifest.package));
|
|
4023
4138
|
if (!dry) {
|
|
4024
|
-
|
|
4025
|
-
|
|
4139
|
+
mkdirSync4(outDir, { recursive: true });
|
|
4140
|
+
writeFileSync8(outFile, `${JSON.stringify(manifest, null, 2)}
|
|
4026
4141
|
`, "utf8");
|
|
4027
4142
|
}
|
|
4028
4143
|
console.log(`${dry ? "[dry] " : ""}sync \u2192 ${outFile} (${manifest.components.length} \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u043E\u0432, ${manifest.version})`);
|
|
4029
4144
|
patchPkgVersions(apiDir, manifest.package, manifest.version, dry);
|
|
4030
|
-
const webDir = opts.
|
|
4145
|
+
const webDir = opts.patchWeb === false ? null : findEluiWebDir(cwd, opts.webDir);
|
|
4031
4146
|
if (webDir)
|
|
4032
4147
|
patchWebDep(webDir, manifest.package, manifest.version, dry);
|
|
4033
4148
|
if (reseed)
|
|
@@ -4042,14 +4157,14 @@ async function emitAndSync(opts) {
|
|
|
4042
4157
|
|
|
4043
4158
|
// src/lib/kit/doctor-kit.ts
|
|
4044
4159
|
async function doctorKitSync(opts) {
|
|
4045
|
-
const cwd =
|
|
4160
|
+
const cwd = resolve7(opts.cwd);
|
|
4046
4161
|
const dry = opts.dry ?? false;
|
|
4047
4162
|
if (!isElcrmLibPackage(cwd))
|
|
4048
4163
|
return false;
|
|
4049
4164
|
const pkg = readPkgAt(cwd);
|
|
4050
4165
|
if (!pkg?.name || !kitPkgSlug(pkg.name))
|
|
4051
4166
|
return false;
|
|
4052
|
-
if (!
|
|
4167
|
+
if (!existsSync15(join17(cwd, "dist"))) {
|
|
4053
4168
|
console.log(c.dim(`
|
|
4054
4169
|
kit: \u043F\u0440\u043E\u043F\u0443\u0441\u043A \u2014 \u043D\u0435\u0442 dist/ (\u0441\u043D\u0430\u0447\u0430\u043B\u0430 npm run build)`));
|
|
4055
4170
|
return false;
|
|
@@ -4061,13 +4176,13 @@ ${dry ? "[dry] " : ""}kit: sync \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442
|
|
|
4061
4176
|
return true;
|
|
4062
4177
|
} catch (err) {
|
|
4063
4178
|
console.warn(c.yellow("kit: " + (err instanceof Error ? err.message : String(err))));
|
|
4064
|
-
console.warn(c.dim(" \u0417\u0430\u0434\u0430\u0439\u0442\u0435
|
|
4179
|
+
console.warn(c.dim(" \u0417\u0430\u0434\u0430\u0439\u0442\u0435 elcrm kit config --api=\u2026 --web=\u2026 --global"));
|
|
4065
4180
|
return false;
|
|
4066
4181
|
}
|
|
4067
4182
|
}
|
|
4068
4183
|
|
|
4069
4184
|
// src/commands/docs.ts
|
|
4070
|
-
import { join as
|
|
4185
|
+
import { join as join19, resolve as resolve8 } from "path";
|
|
4071
4186
|
|
|
4072
4187
|
// src/lib/elcrmDocsCatalog.ts
|
|
4073
4188
|
var ALL_ELCRM_DOCS = [
|
|
@@ -4101,33 +4216,33 @@ function docsForProject(kind, lib) {
|
|
|
4101
4216
|
|
|
4102
4217
|
// src/lib/scaffoldFiles.ts
|
|
4103
4218
|
import {
|
|
4104
|
-
existsSync as
|
|
4105
|
-
mkdirSync as
|
|
4219
|
+
existsSync as existsSync16,
|
|
4220
|
+
mkdirSync as mkdirSync5,
|
|
4106
4221
|
readdirSync as readdirSync9,
|
|
4107
|
-
readFileSync as
|
|
4108
|
-
writeFileSync as
|
|
4222
|
+
readFileSync as readFileSync24,
|
|
4223
|
+
writeFileSync as writeFileSync9
|
|
4109
4224
|
} from "fs";
|
|
4110
|
-
import { dirname as dirname3, join as
|
|
4225
|
+
import { dirname as dirname3, join as join18 } from "path";
|
|
4111
4226
|
function writeScaffoldFile(dest, body, opts) {
|
|
4112
4227
|
if (opts.dry)
|
|
4113
4228
|
return "dry";
|
|
4114
|
-
if (!opts.force &&
|
|
4229
|
+
if (!opts.force && existsSync16(dest))
|
|
4115
4230
|
return "skip";
|
|
4116
|
-
|
|
4117
|
-
|
|
4231
|
+
mkdirSync5(dirname3(dest), { recursive: true });
|
|
4232
|
+
writeFileSync9(dest, body, "utf8");
|
|
4118
4233
|
return "write";
|
|
4119
4234
|
}
|
|
4120
4235
|
function readBundled(relPath) {
|
|
4121
|
-
const full =
|
|
4122
|
-
if (!
|
|
4236
|
+
const full = join18(packageRoot(), "templates", relPath);
|
|
4237
|
+
if (!existsSync16(full)) {
|
|
4123
4238
|
throw new Error(`\u0428\u0430\u0431\u043B\u043E\u043D \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D: ${relPath}`);
|
|
4124
4239
|
}
|
|
4125
|
-
return
|
|
4240
|
+
return readFileSync24(full, "utf8");
|
|
4126
4241
|
}
|
|
4127
4242
|
|
|
4128
4243
|
// src/commands/docs.ts
|
|
4129
4244
|
async function cmdDocs(parsed) {
|
|
4130
|
-
const cwd =
|
|
4245
|
+
const cwd = resolve8(parsed.options.dir || process.cwd());
|
|
4131
4246
|
const dry = hasFlag(parsed, "dry");
|
|
4132
4247
|
const force = hasFlag(parsed, "force") || !hasFlag(parsed, "keep");
|
|
4133
4248
|
const lib = hasFlag(parsed, "lib") || isElcrmLibPackage(cwd);
|
|
@@ -4135,8 +4250,8 @@ async function cmdDocs(parsed) {
|
|
|
4135
4250
|
const names = docsForProject(kind, lib);
|
|
4136
4251
|
console.log(`${dry ? "[dry] " : ""}elcrm docs \u2192 ${cwd}/docs (${kind}${lib ? ", lib" : ""})`);
|
|
4137
4252
|
for (const name of names) {
|
|
4138
|
-
const body = readBundled(
|
|
4139
|
-
const dest =
|
|
4253
|
+
const body = readBundled(join19("elcrm-docs", name));
|
|
4254
|
+
const dest = join19(cwd, "docs", name);
|
|
4140
4255
|
const action = writeScaffoldFile(dest, body, { dry, force });
|
|
4141
4256
|
const mark = action === "write" ? c.green("+") : action === "skip" ? c.gray("=") : c.cyan("~");
|
|
4142
4257
|
console.log(` ${mark} docs/${name}`);
|
|
@@ -4148,7 +4263,7 @@ async function cmdDocs(parsed) {
|
|
|
4148
4263
|
}
|
|
4149
4264
|
|
|
4150
4265
|
// src/commands/cursor.ts
|
|
4151
|
-
import { join as
|
|
4266
|
+
import { join as join20, resolve as resolve9 } from "path";
|
|
4152
4267
|
var ALWAYS = ["elcrm.mdc", "elcrm-packages.mdc", "elcrm-jsdoc.mdc"];
|
|
4153
4268
|
var UI = [
|
|
4154
4269
|
"elcrm-ui.mdc",
|
|
@@ -4164,7 +4279,7 @@ function writeOne(dest, body, dry, force, label) {
|
|
|
4164
4279
|
console.log(` ${mark} ${label}`);
|
|
4165
4280
|
}
|
|
4166
4281
|
async function cmdCursor(parsed) {
|
|
4167
|
-
const cwd =
|
|
4282
|
+
const cwd = resolve9(parsed.options.dir || process.cwd());
|
|
4168
4283
|
const dry = hasFlag(parsed, "dry");
|
|
4169
4284
|
const force = hasFlag(parsed, "force") || !hasFlag(parsed, "keep");
|
|
4170
4285
|
const lib = hasFlag(parsed, "lib") || isElcrmLibPackage(cwd);
|
|
@@ -4177,24 +4292,24 @@ async function cmdCursor(parsed) {
|
|
|
4177
4292
|
];
|
|
4178
4293
|
console.log(`${dry ? "[dry] " : ""}elcrm cursor \u2192 ${cwd}/.cursor (${kind}${lib ? ", lib" : ""})`);
|
|
4179
4294
|
for (const name of ruleNames) {
|
|
4180
|
-
let body = readBundled(
|
|
4295
|
+
let body = readBundled(join20("elcrm-cursor", "rules", name));
|
|
4181
4296
|
if (kind === "server" && (name === "elcrm-server.mdc" || name === "elcrm-rpc.mdc")) {
|
|
4182
4297
|
body = body.replace("alwaysApply: false", "alwaysApply: true").replace(/^globs:.*\n/m, "");
|
|
4183
4298
|
}
|
|
4184
|
-
writeOne(
|
|
4299
|
+
writeOne(join20(cwd, ".cursor", "rules", name), body, dry, force, `.cursor/rules/${name}`);
|
|
4185
4300
|
}
|
|
4186
4301
|
const docs = docsForProject(kind, lib);
|
|
4187
4302
|
for (const name of docs) {
|
|
4188
|
-
const body = readBundled(
|
|
4189
|
-
writeOne(
|
|
4303
|
+
const body = readBundled(join20("elcrm-docs", name));
|
|
4304
|
+
writeOne(join20(cwd, ".cursor", "docs", name), body, dry, force, `.cursor/docs/${name}`);
|
|
4190
4305
|
}
|
|
4191
|
-
writeOne(
|
|
4306
|
+
writeOne(join20(cwd, "AGENTS.md"), readBundled(join20("elcrm-cursor", "AGENTS.md")), dry, force, "AGENTS.md");
|
|
4192
4307
|
console.log(c.gray("\u0410\u0433\u0435\u043D\u0442: AGENTS.md + rules (\u0443\u0437\u043A\u0438\u0435 glob) + .cursor/docs. \u0421\u0434\u0430\u0447\u0430: elcrm test."));
|
|
4193
4308
|
}
|
|
4194
4309
|
|
|
4195
4310
|
// src/commands/doctor.ts
|
|
4196
4311
|
async function cmdDoctor(parsed) {
|
|
4197
|
-
const cwd =
|
|
4312
|
+
const cwd = resolve10(parsed.options.dir || process.cwd());
|
|
4198
4313
|
const dry = hasFlag(parsed, "dry");
|
|
4199
4314
|
const doDocs = hasFlag(parsed, "docs");
|
|
4200
4315
|
const doTest = hasFlag(parsed, "test");
|
|
@@ -4271,7 +4386,7 @@ doctor: \u0433\u043E\u0442\u043E\u0432\u043E (${n} \u043F\u0440\u0430\u0432\u043
|
|
|
4271
4386
|
}
|
|
4272
4387
|
|
|
4273
4388
|
// src/commands/build.ts
|
|
4274
|
-
import { existsSync as
|
|
4389
|
+
import { existsSync as existsSync17 } from "fs";
|
|
4275
4390
|
|
|
4276
4391
|
// src/lib/nextVersion.ts
|
|
4277
4392
|
async function nextVersion() {
|
|
@@ -4294,9 +4409,9 @@ async function nextVersion() {
|
|
|
4294
4409
|
|
|
4295
4410
|
// src/commands/build.ts
|
|
4296
4411
|
function resolveEntrypoint() {
|
|
4297
|
-
if (
|
|
4412
|
+
if (existsSync17("./src/index.js"))
|
|
4298
4413
|
return "./src/index.js";
|
|
4299
|
-
if (
|
|
4414
|
+
if (existsSync17("./src/index.ts"))
|
|
4300
4415
|
return "./src/index.ts";
|
|
4301
4416
|
return "./src/index.js";
|
|
4302
4417
|
}
|
|
@@ -4374,22 +4489,22 @@ async function cmdUuid() {
|
|
|
4374
4489
|
}
|
|
4375
4490
|
|
|
4376
4491
|
// src/commands/postbuild.ts
|
|
4377
|
-
import { resolve as
|
|
4492
|
+
import { resolve as resolve11 } from "path";
|
|
4378
4493
|
|
|
4379
4494
|
// src/vite/postbuild.ts
|
|
4380
4495
|
import {
|
|
4381
|
-
existsSync as
|
|
4496
|
+
existsSync as existsSync18,
|
|
4382
4497
|
readdirSync as readdirSync11,
|
|
4383
|
-
readFileSync as
|
|
4498
|
+
readFileSync as readFileSync26,
|
|
4384
4499
|
rmSync,
|
|
4385
4500
|
statSync as statSync9,
|
|
4386
|
-
writeFileSync as
|
|
4501
|
+
writeFileSync as writeFileSync11
|
|
4387
4502
|
} from "fs";
|
|
4388
|
-
import { join as
|
|
4503
|
+
import { join as join22 } from "path";
|
|
4389
4504
|
|
|
4390
4505
|
// src/vite/concat-css.ts
|
|
4391
|
-
import { readdirSync as readdirSync10, readFileSync as
|
|
4392
|
-
import { join as
|
|
4506
|
+
import { readdirSync as readdirSync10, readFileSync as readFileSync25, writeFileSync as writeFileSync10 } from "fs";
|
|
4507
|
+
import { join as join21 } from "path";
|
|
4393
4508
|
var SKIP_CSS = new Set([
|
|
4394
4509
|
"index.css",
|
|
4395
4510
|
"tokens.css",
|
|
@@ -4405,10 +4520,10 @@ function concatDistCss(options) {
|
|
|
4405
4520
|
...options.skip ?? []
|
|
4406
4521
|
]);
|
|
4407
4522
|
const files = readdirSync10(options.distDir).filter((f) => f.endsWith(".css") && !skip.has(f)).sort();
|
|
4408
|
-
const css = files.map((f) =>
|
|
4523
|
+
const css = files.map((f) => readFileSync25(join21(options.distDir, f), "utf8")).join(`
|
|
4409
4524
|
`);
|
|
4410
|
-
const outPath =
|
|
4411
|
-
|
|
4525
|
+
const outPath = join21(options.distDir, outFile);
|
|
4526
|
+
writeFileSync10(outPath, css);
|
|
4412
4527
|
console.log(`[concat-css] ${files.length} \u0444\u0430\u0439\u043B\u043E\u0432 \u2192 ${outFile}`);
|
|
4413
4528
|
return outPath;
|
|
4414
4529
|
}
|
|
@@ -4426,18 +4541,18 @@ function postbuildLib(options) {
|
|
|
4426
4541
|
outFile: options.cssOutFile ?? "index.css"
|
|
4427
4542
|
});
|
|
4428
4543
|
for (const name of readdirSync11(dist)) {
|
|
4429
|
-
const dir =
|
|
4544
|
+
const dir = join22(dist, name);
|
|
4430
4545
|
if (!statSync9(dir).isDirectory())
|
|
4431
4546
|
continue;
|
|
4432
4547
|
if (keep.has(name))
|
|
4433
4548
|
continue;
|
|
4434
|
-
const impl =
|
|
4435
|
-
const nestedIndex =
|
|
4436
|
-
const flat =
|
|
4437
|
-
const src =
|
|
4549
|
+
const impl = join22(dir, `${name}.d.ts`);
|
|
4550
|
+
const nestedIndex = join22(dir, "index.d.ts");
|
|
4551
|
+
const flat = join22(dist, `${name}.d.ts`);
|
|
4552
|
+
const src = existsSync18(impl) ? impl : existsSync18(nestedIndex) ? nestedIndex : null;
|
|
4438
4553
|
if (src) {
|
|
4439
|
-
const text =
|
|
4440
|
-
|
|
4554
|
+
const text = readFileSync26(src, "utf8").replace(/from ['"]\.\.\/([^'"]+)['"]/g, `from './$1'`);
|
|
4555
|
+
writeFileSync11(flat, text);
|
|
4441
4556
|
console.log(`[postbuild] types \u2192 ${name}.d.ts`);
|
|
4442
4557
|
}
|
|
4443
4558
|
rmSync(dir, { recursive: true, force: true });
|
|
@@ -4448,7 +4563,7 @@ function postbuildLib(options) {
|
|
|
4448
4563
|
// src/commands/postbuild.ts
|
|
4449
4564
|
async function cmdPostbuild(parsed) {
|
|
4450
4565
|
const dir = parsed.options.dir || "./dist";
|
|
4451
|
-
const distDir =
|
|
4566
|
+
const distDir = resolve11(process.cwd(), dir);
|
|
4452
4567
|
postbuildLib({ distDir });
|
|
4453
4568
|
console.log(`[postbuild] \u0433\u043E\u0442\u043E\u0432\u043E: ${distDir}`);
|
|
4454
4569
|
}
|
|
@@ -4516,8 +4631,8 @@ css-sanitize: \u043F\u043E\u0447\u0438\u043D\u0435\u043D\u043E ${cleaned.length}
|
|
|
4516
4631
|
}
|
|
4517
4632
|
|
|
4518
4633
|
// src/commands/audit.ts
|
|
4519
|
-
import { existsSync as
|
|
4520
|
-
import { join as
|
|
4634
|
+
import { existsSync as existsSync19, readFileSync as readFileSync27 } from "fs";
|
|
4635
|
+
import { join as join23, relative as relative4 } from "path";
|
|
4521
4636
|
function scan(cwd) {
|
|
4522
4637
|
const out = [];
|
|
4523
4638
|
const pkg = readPackageJson(cwd);
|
|
@@ -4548,7 +4663,7 @@ function scan(cwd) {
|
|
|
4548
4663
|
}
|
|
4549
4664
|
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r));
|
|
4550
4665
|
for (const file of files) {
|
|
4551
|
-
const text =
|
|
4666
|
+
const text = readFileSync27(file, "utf8");
|
|
4552
4667
|
const rel2 = relative4(cwd, file);
|
|
4553
4668
|
const lines = text.split(/\r?\n/);
|
|
4554
4669
|
lines.forEach((line, i) => {
|
|
@@ -4650,7 +4765,7 @@ function scan(cwd) {
|
|
|
4650
4765
|
return false;
|
|
4651
4766
|
if (/theme(-light|-dark)?\.css$/.test(f))
|
|
4652
4767
|
return false;
|
|
4653
|
-
const t =
|
|
4768
|
+
const t = readFileSync27(f, "utf8");
|
|
4654
4769
|
return t.includes("--field-border:") && t.includes("--button-secondary-bg:") && t.includes("transparent");
|
|
4655
4770
|
});
|
|
4656
4771
|
if (toolbarMarkers.length > 1) {
|
|
@@ -4661,8 +4776,8 @@ function scan(cwd) {
|
|
|
4661
4776
|
fix: "\u043E\u0431\u0449\u0438\u0439 \u043A\u043B\u0430\u0441\u0441 + theme tokens"
|
|
4662
4777
|
});
|
|
4663
4778
|
}
|
|
4664
|
-
const styleDir = ["src/style", "src/styles", "style"].map((d) =>
|
|
4665
|
-
if (styleDir && !
|
|
4779
|
+
const styleDir = ["src/style", "src/styles", "style"].map((d) => join23(cwd, d)).find(existsSync19);
|
|
4780
|
+
if (styleDir && !existsSync19(join23(styleDir, "elcrm.css"))) {
|
|
4666
4781
|
out.push({
|
|
4667
4782
|
level: "info",
|
|
4668
4783
|
code: "elcrm-css",
|
|
@@ -4670,8 +4785,8 @@ function scan(cwd) {
|
|
|
4670
4785
|
fix: "elcrm css"
|
|
4671
4786
|
});
|
|
4672
4787
|
}
|
|
4673
|
-
if (styleDir &&
|
|
4674
|
-
const elcrmCss =
|
|
4788
|
+
if (styleDir && existsSync19(join23(styleDir, "elcrm.css"))) {
|
|
4789
|
+
const elcrmCss = readFileSync27(join23(styleDir, "elcrm.css"), "utf8");
|
|
4675
4790
|
for (const m of elcrmCss.matchAll(/@import\s+["'](@elcrm\/[^"']+)["']/g)) {
|
|
4676
4791
|
const spec = m[1];
|
|
4677
4792
|
if (!resolveElcrmCssImport(spec, cwd)) {
|
|
@@ -4679,7 +4794,7 @@ function scan(cwd) {
|
|
|
4679
4794
|
level: "error",
|
|
4680
4795
|
code: "elcrm-import-missing",
|
|
4681
4796
|
message: `\u0431\u0438\u0442\u044B\u0439 @import "${spec}" \u2014 \u0444\u0430\u0439\u043B\u0430 \u043D\u0435\u0442 \u0432 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u043E\u043C \u043F\u0430\u043A\u0435\u0442\u0435`,
|
|
4682
|
-
file: relative4(cwd,
|
|
4797
|
+
file: relative4(cwd, join23(styleDir, "elcrm.css")),
|
|
4683
4798
|
fix: "elcrm css"
|
|
4684
4799
|
});
|
|
4685
4800
|
}
|
|
@@ -4691,8 +4806,8 @@ function scan(cwd) {
|
|
|
4691
4806
|
"theme-light.css",
|
|
4692
4807
|
"theme-dark.css",
|
|
4693
4808
|
"theme.css"
|
|
4694
|
-
].map((f) =>
|
|
4695
|
-
const themeText = themeFiles.filter(
|
|
4809
|
+
].map((f) => join23(styleDir, f));
|
|
4810
|
+
const themeText = themeFiles.filter(existsSync19).map((f) => readFileSync27(f, "utf8")).join(`
|
|
4696
4811
|
`);
|
|
4697
4812
|
if (themeText && !/--popup-shadow\s*:/.test(themeText) && /--date-popup-shadow\s*:|--select-background\s*:/.test(themeText)) {
|
|
4698
4813
|
out.push({
|
|
@@ -4714,7 +4829,7 @@ function scan(cwd) {
|
|
|
4714
4829
|
for (const file of files) {
|
|
4715
4830
|
if (!file.endsWith(".css"))
|
|
4716
4831
|
continue;
|
|
4717
|
-
const text =
|
|
4832
|
+
const text = readFileSync27(file, "utf8");
|
|
4718
4833
|
const relPath = relative4(cwd, file);
|
|
4719
4834
|
const lines = text.split(/\r?\n/);
|
|
4720
4835
|
let prevNonEmpty = "";
|
|
@@ -4804,7 +4919,7 @@ ${c.cyan("\u2192")} elcrm migrate front${hasFlag(parsed, "dry") ? " --dry" : ""}
|
|
|
4804
4919
|
}
|
|
4805
4920
|
|
|
4806
4921
|
// src/commands/kit.ts
|
|
4807
|
-
import { resolve as
|
|
4922
|
+
import { resolve as resolve12, join as join24 } from "path";
|
|
4808
4923
|
function showKitHelp() {
|
|
4809
4924
|
console.log(`elcrm kit \u2014 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F elUI (UIKit)
|
|
4810
4925
|
|
|
@@ -4819,7 +4934,13 @@ function showKitHelp() {
|
|
|
4819
4934
|
pull [--api=\u2026] [--no-reseed] [--dry]
|
|
4820
4935
|
emit + sync (\u0443\u0434\u043E\u0431\u043D\u043E \u0432 postbuild)
|
|
4821
4936
|
|
|
4822
|
-
|
|
4937
|
+
config [--api=\u2026] [--web=\u2026] [--global] [--local] [--show]
|
|
4938
|
+
\u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u043F\u0443\u0442\u0438 elUI (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E ~/.elcrm/kit-paths.json)
|
|
4939
|
+
|
|
4940
|
+
\u041F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u044B\u0435 (\u043E\u043F\u0446\u0438\u043E\u043D\u0430\u043B\u044C\u043D\u043E): ELUI_API_DIR, ELUI_WEB_DIR
|
|
4941
|
+
|
|
4942
|
+
\u041E\u0434\u0438\u043D \u0440\u0430\u0437:
|
|
4943
|
+
elcrm kit config --api=/path/to/elUI.api --web=/path/to/elUI.web --global
|
|
4823
4944
|
|
|
4824
4945
|
\u041F\u0440\u0438\u043C\u0435\u0440 (components):
|
|
4825
4946
|
npm run build && elcrm kit pull
|
|
@@ -4830,7 +4951,7 @@ function showKitHelp() {
|
|
|
4830
4951
|
}
|
|
4831
4952
|
async function cmdKit(parsed) {
|
|
4832
4953
|
const sub = parsed.positionals[0] || "help";
|
|
4833
|
-
const cwd =
|
|
4954
|
+
const cwd = resolve12(parsed.options.dir || process.cwd());
|
|
4834
4955
|
const dry = hasFlag(parsed, "dry");
|
|
4835
4956
|
const noReseed = hasFlag(parsed, "no-reseed");
|
|
4836
4957
|
if (sub === "help" || sub === "--help") {
|
|
@@ -4860,6 +4981,37 @@ async function cmdKit(parsed) {
|
|
|
4860
4981
|
});
|
|
4861
4982
|
return;
|
|
4862
4983
|
}
|
|
4984
|
+
if (sub === "config") {
|
|
4985
|
+
const global = hasFlag(parsed, "global") || !hasFlag(parsed, "local");
|
|
4986
|
+
const show = hasFlag(parsed, "show") || !parsed.options.api && !parsed.options.web;
|
|
4987
|
+
if (show && !parsed.options.api && !parsed.options.web) {
|
|
4988
|
+
const saved = loadKitPathsConfig(cwd);
|
|
4989
|
+
const api = findEluiApiDir(cwd, parsed.options.api) ?? "(\u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D)";
|
|
4990
|
+
const web = findEluiWebDir(cwd, parsed.options.web) ?? "(\u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D)";
|
|
4991
|
+
console.log("elcrm kit config:");
|
|
4992
|
+
console.log(" \u0444\u0430\u0439\u043B:", global ? "~/.elcrm/kit-paths.json" : ".elcrm/kit-paths.json");
|
|
4993
|
+
console.log(" apiDir (\u0444\u0430\u0439\u043B):", saved.apiDir ?? "\u2014");
|
|
4994
|
+
console.log(" webDir (\u0444\u0430\u0439\u043B):", saved.webDir ?? "\u2014");
|
|
4995
|
+
console.log(" apiDir (resolve):", api);
|
|
4996
|
+
console.log(" webDir (resolve):", web);
|
|
4997
|
+
if (!saved.apiDir) {
|
|
4998
|
+
console.log(c.dim(`
|
|
4999
|
+
\u0417\u0430\u0434\u0430\u0442\u044C: elcrm kit config --api=\u2026 --web=\u2026 --global`));
|
|
5000
|
+
}
|
|
5001
|
+
return;
|
|
5002
|
+
}
|
|
5003
|
+
const next = saveKitPathsConfig(cwd, {
|
|
5004
|
+
...parsed.options.api ? { apiDir: parsed.options.api } : {},
|
|
5005
|
+
...parsed.options.web ? { webDir: parsed.options.web } : {}
|
|
5006
|
+
}, global);
|
|
5007
|
+
const where = global ? "~/.elcrm/kit-paths.json" : join24(cwd, ".elcrm/kit-paths.json");
|
|
5008
|
+
console.log(c.green("kit config \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D \u2192 " + where));
|
|
5009
|
+
if (next.apiDir)
|
|
5010
|
+
console.log(" apiDir:", next.apiDir);
|
|
5011
|
+
if (next.webDir)
|
|
5012
|
+
console.log(" webDir:", next.webDir);
|
|
5013
|
+
return;
|
|
5014
|
+
}
|
|
4863
5015
|
if (sub === "pull") {
|
|
4864
5016
|
if (!isElcrmLibPackage(cwd)) {
|
|
4865
5017
|
console.error(c.red("kit pull \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0432 npm-\u043F\u0430\u043A\u0435\u0442\u0435 @elcrm/components | @elcrm/form"));
|
|
@@ -4867,6 +5019,8 @@ async function cmdKit(parsed) {
|
|
|
4867
5019
|
}
|
|
4868
5020
|
await emitAndSync({
|
|
4869
5021
|
cwd,
|
|
5022
|
+
apiDir: parsed.options.api,
|
|
5023
|
+
webDir: parsed.options.web,
|
|
4870
5024
|
dry,
|
|
4871
5025
|
reseed: !noReseed
|
|
4872
5026
|
});
|
|
@@ -4881,11 +5035,11 @@ async function cmdKit(parsed) {
|
|
|
4881
5035
|
function cliVersion() {
|
|
4882
5036
|
const here = dirname4(fileURLToPath2(import.meta.url));
|
|
4883
5037
|
for (const p of [
|
|
4884
|
-
|
|
4885
|
-
|
|
5038
|
+
join25(here, "..", "package.json"),
|
|
5039
|
+
join25(here, "package.json")
|
|
4886
5040
|
]) {
|
|
4887
5041
|
try {
|
|
4888
|
-
const v = JSON.parse(
|
|
5042
|
+
const v = JSON.parse(readFileSync28(p, "utf8")).version;
|
|
4889
5043
|
if (typeof v === "string" && v)
|
|
4890
5044
|
return v;
|
|
4891
5045
|
} catch {}
|
|
@@ -4921,7 +5075,8 @@ function showHelp() {
|
|
|
4921
5075
|
.cursor/rules + .cursor/docs + AGENTS.md
|
|
4922
5076
|
--lib: \u0447\u0435\u043A\u043B\u0438\u0441\u0442 \u0430\u0432\u0442\u043E\u0440\u0430 @elcrm/*
|
|
4923
5077
|
|
|
4924
|
-
kit <emit|sync|pull> [--api=\u2026] [--web=\u2026] [--no-reseed] [--dry]
|
|
5078
|
+
kit <emit|sync|pull|config> [--api=\u2026] [--web=\u2026] [--no-reseed] [--dry]
|
|
5079
|
+
config \u2014 \u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u043F\u0443\u0442\u0438 \u0432 ~/.elcrm/kit-paths.json (--global)
|
|
4925
5080
|
emit \u2014 manifest \u0438\u0437 dist/*.d.ts (@elcrm/components|form)
|
|
4926
5081
|
sync \u2014 manifest \u2192 elUI.api/src/kit/manifests + reseed
|
|
4927
5082
|
pull \u2014 emit + sync (postbuild \u043F\u0430\u043A\u0435\u0442\u0430)
|
package/package.json
CHANGED
|
@@ -14,7 +14,7 @@ Shell UI: оболочка, шапка, секции, списки, Dropdown / R
|
|
|
14
14
|
import {
|
|
15
15
|
Layout, Header, Footer, Brand, Avatar, AvatarName, AvatarGroup, Badge,
|
|
16
16
|
Menu, Dropdown, Section, NavSections, TabSections, Breadcrumb, Stack,
|
|
17
|
-
Card, Stat, ActionGroup, TextGroup, ItemColumn, List, Item, PageHead, PageShell, ChatList, ChatMessages, ChatSplit, Sidebar, Popover,
|
|
17
|
+
Card, Stat, ActionGroup, Toolbar, TextGroup, ItemColumn, List, Item, PageHead, PageShell, ChatList, ChatMessages, ChatSplit, Sidebar, Popover,
|
|
18
18
|
Healthmap, PanelInfo,
|
|
19
19
|
Loading, EmptyState, RadioGroup, PricingGroup, PricingTable,
|
|
20
20
|
createLazyResolver,
|
|
@@ -37,7 +37,8 @@ import type { PricingPlan, HealthmapData } from "@elcrm/components";
|
|
|
37
37
|
- **Stat** — метрика: `label` + `value`, `tone` как у Badge, `labelMuted`. Не собирать из `span` в приложении.
|
|
38
38
|
- **Healthmap** — теплокарта дней (`data.days`). Данные грузит приложение; слоты `brandName` / `brandSub` / `unit` / `hint`. Токены `--healthmap-cell`, `--healthmap-gap`, `--healthmap-l0`…`l4`.
|
|
39
39
|
- **PanelInfo** — выезд справа (шапка / body / footer). На узком экране — оверлей. Слоты: `children`, `footer`, `headerExtra`, `close`. Токены `--panel-info-width`, `--panel-info-width-min`, `--panel-info-overlay-max`, `--panel-info-backdrop`.
|
|
40
|
-
- **ActionGroup** —
|
|
40
|
+
- **ActionGroup** — ряд иконок в карточке / строке: `label` + `items` и/или `children`. Кнопки — `@elcrm/button`.
|
|
41
|
+
- **Toolbar** — фильтры над списком. `size` (`s`/`m`/`l`, по умолчанию `s`) наследуют вложенные `*Field`, `Search`, `Button`, `Dropdown` (свой `size` важнее). `align`: `start` / `center` / `end` / `between`. `width`: `l` (100%, по умолчанию) или `s` (по контенту, не растягивать). Токены `--toolbar-gap`. Не `ActionGroup`.
|
|
41
42
|
- **TextGroup** — две строки: `title` + `description` (без аватара; с аватаром — AvatarName).
|
|
42
43
|
- **Item** — строка списка. `as` button/a/li, `active`. `variant="card"` — рамка и muted-фон (идеи / тикеты / inbox). Не дублировать `.desk-row` в приложении.
|
|
43
44
|
- **ItemColumn** — внутри Item: `icon` слева, столбик `title` / `description` / `footer` или `meta`, `extra` — бейджи справа сверху, `aside` — колонка справа. `unread` — жирный title. Title: `--item-column-title-size` / `--item-column-title-line` (в console = `--button-size-s` / `--button-line-height`).
|
|
@@ -45,7 +46,7 @@ import type { PricingPlan, HealthmapData } from "@elcrm/components";
|
|
|
45
46
|
## Меню
|
|
46
47
|
|
|
47
48
|
- **Menu** — inline-навигация в шапке. `items`: `value` + `label` + `badge` (`0` не показываем, иначе `Badge` size s). `variant="line"` — вкладки с чертой снизу (не ломать pill селекторами страницы).
|
|
48
|
-
- **Dropdown** — выпадающее меню по `items`/`groups` (portal). `placement="auto"|"top"|"bottom"` — куда открывать панель (футер Sidebar — `top`).
|
|
49
|
+
- **Dropdown** — выпадающее меню по `items`/`groups` (portal). `placement="auto"|"top"|"bottom"` — куда открывать панель (футер Sidebar — `top`). `size` — высота триггера; в `Toolbar` берётся сам.
|
|
49
50
|
- **Popover** — свой попап в portal (якорь + `children`). z-index: `acquireOverlayZIndex` (тот же стек, что у form). Не `@elcrm/overlay` `Menu`. `placement` как у Dropdown: позиция по **реальной** высоте панели, не по `maxHeight` 420.
|
|
50
51
|
|
|
51
52
|
## Avatar
|
|
@@ -65,6 +66,7 @@ import type { PricingPlan, HealthmapData } from "@elcrm/components";
|
|
|
65
66
|
- `--layout-padding` / `--layout-margin` / `--layout-max-width` — отступы и макс. ширина корня Layout (`0` / `none` = на весь вьюпорт).
|
|
66
67
|
- `--header-border` — рамка Header (shorthand: все стороны и толщина). Только снизу: `none` + линия через `--header-shadow`.
|
|
67
68
|
- `--header-nav-justify` — выравнивание `nav` в шапке (`flex-start` / `center` / `flex-end`).
|
|
69
|
+
- `<Toolbar size="s" width="l" align="start">` — один размер для Search / `*Field` / Button / Dropdown. `width="s"` — ряд по контенту. Свой `size` у ребёнка важнее.
|
|
68
70
|
- Узкие токены (`--chat-*`, `--sidebar-*`, `--item-column-*`) по умолчанию = `--shell-*`. Переопределяй только отличие.
|
|
69
71
|
- Задать `--shell-color` / `--shell-padding` / `--shell-radius` один раз — большинство компонентов подхватят.
|
|
70
72
|
- `--popup-shadow` общий с `@elcrm/form`.
|
|
@@ -23,7 +23,8 @@ const form = useForm({ login: "", password: "" });
|
|
|
23
23
|
|
|
24
24
|
Канонические поля: `StringField`, `PasswordField`, `TextareaField`, `NumberField`, `PercentField`, `MoneyField`, `MaskField`, `PhoneField`, `EmailField`, `UrlField`, `DateField`, `TimeField`, `SelectField`, `OptionsField`, `ModalField`, `RangeField`, `CheckField`, `RadioField`, `TagsField`, `RatingField`, `CodeField`, `FileField`, `DragDropField`, `RichTextField`, `ColorField`, `HiddenField`, `DisplayField`, `SearchField`, `TabsField`.
|
|
25
25
|
|
|
26
|
-
`disabled`, `size` (`"s"` | `"m"` | `"l"`) — у всех видимых `*Field` (кроме `HiddenField`).
|
|
26
|
+
`disabled`, `size` (`"s"` | `"m"` | `"l"`) — у всех видимых `*Field` (кроме `HiddenField`).
|
|
27
|
+
В ряду фильтров — `<Toolbar size="s">` из `@elcrm/components`: вложенные поля/Search/Button берут этот `size`.
|
|
27
28
|
|
|
28
29
|
`PasswordField`: `generate` — кнопка случайного пароля. `true` → `Az09#` (A–Z, a–z, 0–9, символы). `generate="A"` только заглавные, `"59"` цифры 5–9, `"#"` только символы. Длина — `maxLength` или 12.
|
|
29
30
|
|
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
--item-column-title-line: 1.3;
|
|
135
135
|
--stat-value-size: 1.75rem;
|
|
136
136
|
--action-group-gap: var(--shell-gap-sm);
|
|
137
|
+
--toolbar-gap: var(--shell-gap-sm);
|
|
137
138
|
--sidebar-width: 260px;
|
|
138
139
|
--sidebar-pad-x: var(--shell-gap);
|
|
139
140
|
--sidebar-pad-y: var(--shell-gap-lg);
|
|
@@ -145,6 +145,7 @@
|
|
|
145
145
|
--item-column-title-line: 1.3;
|
|
146
146
|
--stat-value-size: 1.75rem;
|
|
147
147
|
--action-group-gap: var(--shell-gap-sm);
|
|
148
|
+
--toolbar-gap: var(--shell-gap-sm);
|
|
148
149
|
--sidebar-width: 248px;
|
|
149
150
|
--sidebar-pad-x: var(--shell-gap);
|
|
150
151
|
--sidebar-pad-y: var(--shell-gap-lg);
|