elcrm 1.1.19 → 1.1.21
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 +669 -70
- package/package.json +3 -3
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
|
|
@@ -35,7 +35,9 @@ function parseArgs(argv = process.argv.slice(2)) {
|
|
|
35
35
|
"name",
|
|
36
36
|
"dir",
|
|
37
37
|
"folder",
|
|
38
|
-
"out"
|
|
38
|
+
"out",
|
|
39
|
+
"api",
|
|
40
|
+
"web"
|
|
39
41
|
]);
|
|
40
42
|
if (valueOpts.has(body)) {
|
|
41
43
|
options[body] = next;
|
|
@@ -3669,10 +3671,11 @@ async function cmdMigrate(parsed) {
|
|
|
3669
3671
|
}
|
|
3670
3672
|
|
|
3671
3673
|
// src/commands/doctor.ts
|
|
3672
|
-
import { resolve as
|
|
3674
|
+
import { resolve as resolve10 } from "path";
|
|
3673
3675
|
|
|
3674
|
-
// src/
|
|
3675
|
-
import {
|
|
3676
|
+
// src/lib/kit/doctor-kit.ts
|
|
3677
|
+
import { existsSync as existsSync15 } from "fs";
|
|
3678
|
+
import { join as join17, resolve as resolve7 } from "path";
|
|
3676
3679
|
|
|
3677
3680
|
// src/lib/projectKind.ts
|
|
3678
3681
|
function detectProjectKind(cwd) {
|
|
@@ -3702,6 +3705,478 @@ function isElcrmLibPackage(cwd) {
|
|
|
3702
3705
|
return typeof name === "string" && name.startsWith("@elcrm/");
|
|
3703
3706
|
}
|
|
3704
3707
|
|
|
3708
|
+
// src/lib/kit/paths.ts
|
|
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";
|
|
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
|
+
}
|
|
3740
|
+
function readName(dir) {
|
|
3741
|
+
try {
|
|
3742
|
+
const j = JSON.parse(readFileSync19(join12(dir, "package.json"), "utf8"));
|
|
3743
|
+
return j.name ?? null;
|
|
3744
|
+
} catch {
|
|
3745
|
+
return null;
|
|
3746
|
+
}
|
|
3747
|
+
}
|
|
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
|
+
}
|
|
3810
|
+
const env = process.env.ELUI_API_DIR?.trim();
|
|
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);
|
|
3817
|
+
for (let i = 0;i < 8; i++) {
|
|
3818
|
+
for (const name of ["elUI.api", "ui-kit.api"]) {
|
|
3819
|
+
const candidate = join13(dir, name);
|
|
3820
|
+
if (existsSync13(join13(candidate, "src/kit/catalog.ts")))
|
|
3821
|
+
return candidate;
|
|
3822
|
+
}
|
|
3823
|
+
const parent = join13(dir, "..");
|
|
3824
|
+
if (parent === dir)
|
|
3825
|
+
break;
|
|
3826
|
+
dir = parent;
|
|
3827
|
+
}
|
|
3828
|
+
return null;
|
|
3829
|
+
}
|
|
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
|
+
}
|
|
3837
|
+
const env = process.env.ELUI_WEB_DIR?.trim();
|
|
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);
|
|
3844
|
+
for (let i = 0;i < 8; i++) {
|
|
3845
|
+
for (const name of ["elUI.web", "Uikit.web"]) {
|
|
3846
|
+
const candidate = join13(dir, name);
|
|
3847
|
+
if (readName2(candidate) === "elui-web")
|
|
3848
|
+
return candidate;
|
|
3849
|
+
}
|
|
3850
|
+
dir = join13(dir, "..");
|
|
3851
|
+
}
|
|
3852
|
+
return null;
|
|
3853
|
+
}
|
|
3854
|
+
function kitPkgSlug(npmName) {
|
|
3855
|
+
if (npmName === "@elcrm/components")
|
|
3856
|
+
return "components";
|
|
3857
|
+
if (npmName === "@elcrm/form")
|
|
3858
|
+
return "form";
|
|
3859
|
+
return null;
|
|
3860
|
+
}
|
|
3861
|
+
function manifestFileName(npmName) {
|
|
3862
|
+
return npmName.replace("@", "").replace("/", "-") + ".json";
|
|
3863
|
+
}
|
|
3864
|
+
|
|
3865
|
+
// src/lib/kit/sync.ts
|
|
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";
|
|
3868
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
3869
|
+
|
|
3870
|
+
// src/lib/kit/emit.ts
|
|
3871
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync22, writeFileSync as writeFileSync7 } from "fs";
|
|
3872
|
+
import { join as join15, resolve as resolve5 } from "path";
|
|
3873
|
+
|
|
3874
|
+
// src/lib/kit/parse-dts.ts
|
|
3875
|
+
import { readFileSync as readFileSync21, readdirSync as readdirSync8, statSync as statSync8 } from "fs";
|
|
3876
|
+
import { basename, join as join14 } from "path";
|
|
3877
|
+
var SKIP_SLUGS = new Set([
|
|
3878
|
+
"index",
|
|
3879
|
+
"types",
|
|
3880
|
+
"cx",
|
|
3881
|
+
"overlayZ",
|
|
3882
|
+
"lazyRoute",
|
|
3883
|
+
"stackGap",
|
|
3884
|
+
"rovingKeys",
|
|
3885
|
+
"CheckIcon",
|
|
3886
|
+
"useControllableValue",
|
|
3887
|
+
"badgeText"
|
|
3888
|
+
]);
|
|
3889
|
+
function isMainComponentDoc(doc) {
|
|
3890
|
+
if (!doc)
|
|
3891
|
+
return false;
|
|
3892
|
+
if (doc.includes("@example"))
|
|
3893
|
+
return true;
|
|
3894
|
+
const lines = doc.split(`
|
|
3895
|
+
`).filter((l) => l.trim());
|
|
3896
|
+
if (lines.length >= 2)
|
|
3897
|
+
return true;
|
|
3898
|
+
if (/^Props\s/i.test(doc.trim()))
|
|
3899
|
+
return false;
|
|
3900
|
+
return doc.length > 72;
|
|
3901
|
+
}
|
|
3902
|
+
function componentDoc(content, slug) {
|
|
3903
|
+
const fnAnchor = "export declare function " + slug;
|
|
3904
|
+
const propsAnchor = "export type " + slug + "Props";
|
|
3905
|
+
const fnDoc = leadingDoc(content, fnAnchor);
|
|
3906
|
+
const propsDoc = leadingDoc(content, propsAnchor);
|
|
3907
|
+
if (isMainComponentDoc(fnDoc))
|
|
3908
|
+
return fnDoc;
|
|
3909
|
+
if (isMainComponentDoc(propsDoc))
|
|
3910
|
+
return propsDoc;
|
|
3911
|
+
return fnDoc || propsDoc;
|
|
3912
|
+
}
|
|
3913
|
+
function leadingDoc(content, anchor) {
|
|
3914
|
+
const idx = content.indexOf(anchor);
|
|
3915
|
+
if (idx < 0)
|
|
3916
|
+
return "";
|
|
3917
|
+
const head = content.slice(0, idx).trimEnd();
|
|
3918
|
+
const start = head.lastIndexOf("/**");
|
|
3919
|
+
if (start < 0)
|
|
3920
|
+
return "";
|
|
3921
|
+
const end = head.indexOf("*/", start);
|
|
3922
|
+
if (end < 0)
|
|
3923
|
+
return "";
|
|
3924
|
+
return head.slice(start + 3, end).split(`
|
|
3925
|
+
`).map((l) => l.replace(/^\s*\*\s?/, "").trimEnd()).join(`
|
|
3926
|
+
`).trim();
|
|
3927
|
+
}
|
|
3928
|
+
function examplesFromDoc(doc) {
|
|
3929
|
+
const out = [];
|
|
3930
|
+
const fence = String.fromCharCode(96, 96, 96);
|
|
3931
|
+
const re = new RegExp("@example\\s*\\n?\\s*" + fence + "[\\w]*\\s*\\n([\\s\\S]*?)" + fence, "g");
|
|
3932
|
+
let m;
|
|
3933
|
+
let i = 0;
|
|
3934
|
+
while (m = re.exec(doc)) {
|
|
3935
|
+
const code = m[1].trim();
|
|
3936
|
+
if (!code)
|
|
3937
|
+
continue;
|
|
3938
|
+
out.push({
|
|
3939
|
+
title: i === 0 ? "\u041F\u0440\u0438\u043C\u0435\u0440" : "\u041F\u0440\u0438\u043C\u0435\u0440 " + (i + 1),
|
|
3940
|
+
code
|
|
3941
|
+
});
|
|
3942
|
+
i++;
|
|
3943
|
+
}
|
|
3944
|
+
return out;
|
|
3945
|
+
}
|
|
3946
|
+
function descriptionFromDoc(doc) {
|
|
3947
|
+
const lines = doc.split(`
|
|
3948
|
+
`).map((l) => l.trim()).filter(Boolean);
|
|
3949
|
+
const parts = [];
|
|
3950
|
+
for (const line of lines) {
|
|
3951
|
+
if (line.startsWith("@"))
|
|
3952
|
+
break;
|
|
3953
|
+
parts.push(line);
|
|
3954
|
+
}
|
|
3955
|
+
return parts.join(" ").replace(/\s+/g, " ").trim();
|
|
3956
|
+
}
|
|
3957
|
+
function propsFromPropsBlock(block) {
|
|
3958
|
+
const out = [];
|
|
3959
|
+
const re = /\/\*\*([\s\S]*?)\*\/\s*(?:readonly\s+)?(\w+)\??\s*:\s*([^;]+);/g;
|
|
3960
|
+
let m;
|
|
3961
|
+
while (m = re.exec(block)) {
|
|
3962
|
+
const name = m[2];
|
|
3963
|
+
if (name === "className" || name.startsWith("__"))
|
|
3964
|
+
continue;
|
|
3965
|
+
const doc = m[1].split(`
|
|
3966
|
+
`).map((l) => l.replace(/^\s*\*\s?/, "").trim()).filter(Boolean).join(" ");
|
|
3967
|
+
out.push({
|
|
3968
|
+
name,
|
|
3969
|
+
type: m[3].replace(/\s+/g, " ").trim(),
|
|
3970
|
+
description: doc
|
|
3971
|
+
});
|
|
3972
|
+
}
|
|
3973
|
+
return out;
|
|
3974
|
+
}
|
|
3975
|
+
function parseComponentDts(content, slug) {
|
|
3976
|
+
if (!new RegExp("export declare function " + slug + "\\b").test(content)) {
|
|
3977
|
+
return null;
|
|
3978
|
+
}
|
|
3979
|
+
const doc = componentDoc(content, slug);
|
|
3980
|
+
const propsMatch = content.match(new RegExp("export type " + slug + "Props\\s*=\\s*([\\s\\S]*?);\\s*(?:export|$)"));
|
|
3981
|
+
const propsBlock = propsMatch?.[1] ?? "";
|
|
3982
|
+
return {
|
|
3983
|
+
slug,
|
|
3984
|
+
title: slug,
|
|
3985
|
+
description: descriptionFromDoc(doc) || slug,
|
|
3986
|
+
importFrom: "@elcrm/components",
|
|
3987
|
+
examples: examplesFromDoc(doc),
|
|
3988
|
+
props: propsFromPropsBlock(propsBlock)
|
|
3989
|
+
};
|
|
3990
|
+
}
|
|
3991
|
+
function scanDistComponents(distDir, importFrom) {
|
|
3992
|
+
const out = [];
|
|
3993
|
+
for (const name of readdirSync8(distDir)) {
|
|
3994
|
+
if (!name.endsWith(".d.ts"))
|
|
3995
|
+
continue;
|
|
3996
|
+
const slug = basename(name, ".d.ts");
|
|
3997
|
+
if (SKIP_SLUGS.has(slug) || slug.includes("."))
|
|
3998
|
+
continue;
|
|
3999
|
+
const path = join14(distDir, name);
|
|
4000
|
+
if (!statSync8(path).isFile())
|
|
4001
|
+
continue;
|
|
4002
|
+
const content = readFileSync21(path, "utf8");
|
|
4003
|
+
const parsed = parseComponentDts(content, slug);
|
|
4004
|
+
if (!parsed)
|
|
4005
|
+
continue;
|
|
4006
|
+
parsed.importFrom = importFrom;
|
|
4007
|
+
out.push(parsed);
|
|
4008
|
+
}
|
|
4009
|
+
out.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
4010
|
+
return out;
|
|
4011
|
+
}
|
|
4012
|
+
|
|
4013
|
+
// src/lib/kit/emit.ts
|
|
4014
|
+
function readPkg(cwd) {
|
|
4015
|
+
const j = JSON.parse(readFileSync22(join15(cwd, "package.json"), "utf8"));
|
|
4016
|
+
if (!j.name?.startsWith("@elcrm/")) {
|
|
4017
|
+
throw new Error("elcrm kit emit \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0432 npm-\u043F\u0430\u043A\u0435\u0442\u0435 @elcrm/*");
|
|
4018
|
+
}
|
|
4019
|
+
return { name: j.name, version: j.version ?? "0.0.0" };
|
|
4020
|
+
}
|
|
4021
|
+
function emitKitManifest(cwd) {
|
|
4022
|
+
const pkg = readPkg(cwd);
|
|
4023
|
+
const pkgSlug = kitPkgSlug(pkg.name);
|
|
4024
|
+
if (!pkgSlug) {
|
|
4025
|
+
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)`);
|
|
4026
|
+
}
|
|
4027
|
+
const distDir = join15(cwd, "dist");
|
|
4028
|
+
const components = scanDistComponents(distDir, pkg.name).map((c2) => ({
|
|
4029
|
+
...c2,
|
|
4030
|
+
importFrom: pkg.name
|
|
4031
|
+
}));
|
|
4032
|
+
return {
|
|
4033
|
+
format: "elcrm-kit-manifest-v1",
|
|
4034
|
+
package: pkg.name,
|
|
4035
|
+
version: pkg.version,
|
|
4036
|
+
pkg: pkgSlug,
|
|
4037
|
+
generatedAt: new Date().toISOString(),
|
|
4038
|
+
components
|
|
4039
|
+
};
|
|
4040
|
+
}
|
|
4041
|
+
function writeKitManifest(cwd, manifest, dry = false) {
|
|
4042
|
+
const written = [];
|
|
4043
|
+
const targets = [
|
|
4044
|
+
join15(cwd, ".elcrm", "kit-manifest.json"),
|
|
4045
|
+
join15(cwd, "dist", "kit-manifest.json")
|
|
4046
|
+
];
|
|
4047
|
+
const body = `${JSON.stringify(manifest, null, 2)}
|
|
4048
|
+
`;
|
|
4049
|
+
for (const path of targets) {
|
|
4050
|
+
if (dry) {
|
|
4051
|
+
written.push(path);
|
|
4052
|
+
continue;
|
|
4053
|
+
}
|
|
4054
|
+
mkdirSync3(join15(path, ".."), { recursive: true });
|
|
4055
|
+
writeFileSync7(path, body, "utf8");
|
|
4056
|
+
written.push(path);
|
|
4057
|
+
}
|
|
4058
|
+
return written;
|
|
4059
|
+
}
|
|
4060
|
+
function readKitManifest(path) {
|
|
4061
|
+
return JSON.parse(readFileSync22(resolve5(path), "utf8"));
|
|
4062
|
+
}
|
|
4063
|
+
|
|
4064
|
+
// src/lib/kit/sync.ts
|
|
4065
|
+
function patchPkgVersions(apiDir, npmName, version, dry) {
|
|
4066
|
+
const path = join16(apiDir, "src/kit/pkg-versions.ts");
|
|
4067
|
+
let src = readFileSync23(path, "utf8");
|
|
4068
|
+
const re = new RegExp(`("${npmName.replace("/", "\\/")}"\\s*:\\s*")[^"]+(")`);
|
|
4069
|
+
if (!re.test(src)) {
|
|
4070
|
+
console.warn(c.yellow(` ! FALLBACK_DEPS: \u043D\u0435\u0442 ${npmName} \u0432 pkg-versions.ts`));
|
|
4071
|
+
return;
|
|
4072
|
+
}
|
|
4073
|
+
const next = src.replace(re, `$1${version}$2`);
|
|
4074
|
+
if (next === src)
|
|
4075
|
+
return;
|
|
4076
|
+
if (!dry)
|
|
4077
|
+
writeFileSync8(path, next, "utf8");
|
|
4078
|
+
console.log(` ${dry ? "~" : c.green("+")} pkg-versions \u2192 ${npmName} ${version}`);
|
|
4079
|
+
}
|
|
4080
|
+
function patchWebDep(webDir, npmName, version, dry) {
|
|
4081
|
+
const path = join16(webDir, "package.json");
|
|
4082
|
+
const j = JSON.parse(readFileSync23(path, "utf8"));
|
|
4083
|
+
if (!j.dependencies?.[npmName])
|
|
4084
|
+
return;
|
|
4085
|
+
j.dependencies[npmName] = version;
|
|
4086
|
+
if (!dry)
|
|
4087
|
+
writeFileSync8(path, `${JSON.stringify(j, null, 2)}
|
|
4088
|
+
`, "utf8");
|
|
4089
|
+
console.log(` ${dry ? "~" : c.green("+")} elUI.web \u2192 ${npmName}@${version}`);
|
|
4090
|
+
}
|
|
4091
|
+
function runReseed(apiDir, webDir, dry) {
|
|
4092
|
+
if (dry) {
|
|
4093
|
+
console.log(c.gray(" [dry] bun run kit:reseed"));
|
|
4094
|
+
return;
|
|
4095
|
+
}
|
|
4096
|
+
const env = { ...process.env, KIT_RESEED: "1" };
|
|
4097
|
+
if (webDir)
|
|
4098
|
+
env.ELUI_WEB_DIR = webDir;
|
|
4099
|
+
const r = spawnSync2("bun", ["run", "kit:reseed"], {
|
|
4100
|
+
cwd: apiDir,
|
|
4101
|
+
env,
|
|
4102
|
+
stdio: "inherit"
|
|
4103
|
+
});
|
|
4104
|
+
if (r.status !== 0)
|
|
4105
|
+
throw new Error("kit:reseed \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0441\u044F \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439");
|
|
4106
|
+
}
|
|
4107
|
+
async function syncKitManifest(opts) {
|
|
4108
|
+
const cwd = resolve6(opts.cwd);
|
|
4109
|
+
const dry = opts.dry ?? false;
|
|
4110
|
+
const reseed = opts.reseed !== false;
|
|
4111
|
+
persistKitPathsFromOpts({
|
|
4112
|
+
cwd,
|
|
4113
|
+
apiDir: opts.apiDir,
|
|
4114
|
+
webDir: opts.webDir,
|
|
4115
|
+
dry
|
|
4116
|
+
});
|
|
4117
|
+
let manifest;
|
|
4118
|
+
if (opts.manifestPath) {
|
|
4119
|
+
manifest = readKitManifest(opts.manifestPath);
|
|
4120
|
+
} else if (existsSync14(join16(cwd, ".elcrm", "kit-manifest.json"))) {
|
|
4121
|
+
manifest = readKitManifest(join16(cwd, ".elcrm", "kit-manifest.json"));
|
|
4122
|
+
} else {
|
|
4123
|
+
manifest = emitKitManifest(cwd);
|
|
4124
|
+
}
|
|
4125
|
+
const apiDir = findEluiApiDir(cwd, opts.apiDir);
|
|
4126
|
+
if (!apiDir) {
|
|
4127
|
+
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");
|
|
4128
|
+
}
|
|
4129
|
+
const outDir = join16(apiDir, "src/kit/manifests");
|
|
4130
|
+
const outFile = join16(outDir, manifestFileName(manifest.package));
|
|
4131
|
+
if (!dry) {
|
|
4132
|
+
mkdirSync4(outDir, { recursive: true });
|
|
4133
|
+
writeFileSync8(outFile, `${JSON.stringify(manifest, null, 2)}
|
|
4134
|
+
`, "utf8");
|
|
4135
|
+
}
|
|
4136
|
+
console.log(`${dry ? "[dry] " : ""}sync \u2192 ${outFile} (${manifest.components.length} \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u043E\u0432, ${manifest.version})`);
|
|
4137
|
+
patchPkgVersions(apiDir, manifest.package, manifest.version, dry);
|
|
4138
|
+
const webDir = opts.patchWeb === false ? null : findEluiWebDir(cwd, opts.webDir);
|
|
4139
|
+
if (webDir)
|
|
4140
|
+
patchWebDep(webDir, manifest.package, manifest.version, dry);
|
|
4141
|
+
if (reseed)
|
|
4142
|
+
runReseed(apiDir, webDir, dry);
|
|
4143
|
+
}
|
|
4144
|
+
async function emitAndSync(opts) {
|
|
4145
|
+
const manifest = emitKitManifest(opts.cwd);
|
|
4146
|
+
writeKitManifest(opts.cwd, manifest, opts.dry);
|
|
4147
|
+
console.log(`elcrm kit emit: ${manifest.components.length} \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u043E\u0432 \u2192 .elcrm/ + dist/`);
|
|
4148
|
+
await syncKitManifest({ ...opts, cwd: opts.cwd, manifestPath: undefined });
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4151
|
+
// src/lib/kit/doctor-kit.ts
|
|
4152
|
+
async function doctorKitSync(opts) {
|
|
4153
|
+
const cwd = resolve7(opts.cwd);
|
|
4154
|
+
const dry = opts.dry ?? false;
|
|
4155
|
+
if (!isElcrmLibPackage(cwd))
|
|
4156
|
+
return false;
|
|
4157
|
+
const pkg = readPkgAt(cwd);
|
|
4158
|
+
if (!pkg?.name || !kitPkgSlug(pkg.name))
|
|
4159
|
+
return false;
|
|
4160
|
+
if (!existsSync15(join17(cwd, "dist"))) {
|
|
4161
|
+
console.log(c.dim(`
|
|
4162
|
+
kit: \u043F\u0440\u043E\u043F\u0443\u0441\u043A \u2014 \u043D\u0435\u0442 dist/ (\u0441\u043D\u0430\u0447\u0430\u043B\u0430 npm run build)`));
|
|
4163
|
+
return false;
|
|
4164
|
+
}
|
|
4165
|
+
console.log(`
|
|
4166
|
+
${dry ? "[dry] " : ""}kit: sync \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u0438 elUI (${pkg.name})\u2026`);
|
|
4167
|
+
try {
|
|
4168
|
+
await emitAndSync({ cwd, dry, reseed: false });
|
|
4169
|
+
return true;
|
|
4170
|
+
} catch (err) {
|
|
4171
|
+
console.warn(c.yellow("kit: " + (err instanceof Error ? err.message : String(err))));
|
|
4172
|
+
console.warn(c.dim(" \u0417\u0430\u0434\u0430\u0439\u0442\u0435 elcrm kit config --api=\u2026 --web=\u2026 --global"));
|
|
4173
|
+
return false;
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
|
|
4177
|
+
// src/commands/docs.ts
|
|
4178
|
+
import { join as join19, resolve as resolve8 } from "path";
|
|
4179
|
+
|
|
3705
4180
|
// src/lib/elcrmDocsCatalog.ts
|
|
3706
4181
|
var ALL_ELCRM_DOCS = [
|
|
3707
4182
|
"CLI.elCRM.md",
|
|
@@ -3734,33 +4209,33 @@ function docsForProject(kind, lib) {
|
|
|
3734
4209
|
|
|
3735
4210
|
// src/lib/scaffoldFiles.ts
|
|
3736
4211
|
import {
|
|
3737
|
-
existsSync as
|
|
3738
|
-
mkdirSync as
|
|
3739
|
-
readdirSync as
|
|
3740
|
-
readFileSync as
|
|
3741
|
-
writeFileSync as
|
|
4212
|
+
existsSync as existsSync16,
|
|
4213
|
+
mkdirSync as mkdirSync5,
|
|
4214
|
+
readdirSync as readdirSync9,
|
|
4215
|
+
readFileSync as readFileSync24,
|
|
4216
|
+
writeFileSync as writeFileSync9
|
|
3742
4217
|
} from "fs";
|
|
3743
|
-
import { dirname as dirname3, join as
|
|
4218
|
+
import { dirname as dirname3, join as join18 } from "path";
|
|
3744
4219
|
function writeScaffoldFile(dest, body, opts) {
|
|
3745
4220
|
if (opts.dry)
|
|
3746
4221
|
return "dry";
|
|
3747
|
-
if (!opts.force &&
|
|
4222
|
+
if (!opts.force && existsSync16(dest))
|
|
3748
4223
|
return "skip";
|
|
3749
|
-
|
|
3750
|
-
|
|
4224
|
+
mkdirSync5(dirname3(dest), { recursive: true });
|
|
4225
|
+
writeFileSync9(dest, body, "utf8");
|
|
3751
4226
|
return "write";
|
|
3752
4227
|
}
|
|
3753
4228
|
function readBundled(relPath) {
|
|
3754
|
-
const full =
|
|
3755
|
-
if (!
|
|
4229
|
+
const full = join18(packageRoot(), "templates", relPath);
|
|
4230
|
+
if (!existsSync16(full)) {
|
|
3756
4231
|
throw new Error(`\u0428\u0430\u0431\u043B\u043E\u043D \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D: ${relPath}`);
|
|
3757
4232
|
}
|
|
3758
|
-
return
|
|
4233
|
+
return readFileSync24(full, "utf8");
|
|
3759
4234
|
}
|
|
3760
4235
|
|
|
3761
4236
|
// src/commands/docs.ts
|
|
3762
4237
|
async function cmdDocs(parsed) {
|
|
3763
|
-
const cwd =
|
|
4238
|
+
const cwd = resolve8(parsed.options.dir || process.cwd());
|
|
3764
4239
|
const dry = hasFlag(parsed, "dry");
|
|
3765
4240
|
const force = hasFlag(parsed, "force") || !hasFlag(parsed, "keep");
|
|
3766
4241
|
const lib = hasFlag(parsed, "lib") || isElcrmLibPackage(cwd);
|
|
@@ -3768,8 +4243,8 @@ async function cmdDocs(parsed) {
|
|
|
3768
4243
|
const names = docsForProject(kind, lib);
|
|
3769
4244
|
console.log(`${dry ? "[dry] " : ""}elcrm docs \u2192 ${cwd}/docs (${kind}${lib ? ", lib" : ""})`);
|
|
3770
4245
|
for (const name of names) {
|
|
3771
|
-
const body = readBundled(
|
|
3772
|
-
const dest =
|
|
4246
|
+
const body = readBundled(join19("elcrm-docs", name));
|
|
4247
|
+
const dest = join19(cwd, "docs", name);
|
|
3773
4248
|
const action = writeScaffoldFile(dest, body, { dry, force });
|
|
3774
4249
|
const mark = action === "write" ? c.green("+") : action === "skip" ? c.gray("=") : c.cyan("~");
|
|
3775
4250
|
console.log(` ${mark} docs/${name}`);
|
|
@@ -3781,7 +4256,7 @@ async function cmdDocs(parsed) {
|
|
|
3781
4256
|
}
|
|
3782
4257
|
|
|
3783
4258
|
// src/commands/cursor.ts
|
|
3784
|
-
import { join as
|
|
4259
|
+
import { join as join20, resolve as resolve9 } from "path";
|
|
3785
4260
|
var ALWAYS = ["elcrm.mdc", "elcrm-packages.mdc", "elcrm-jsdoc.mdc"];
|
|
3786
4261
|
var UI = [
|
|
3787
4262
|
"elcrm-ui.mdc",
|
|
@@ -3797,7 +4272,7 @@ function writeOne(dest, body, dry, force, label) {
|
|
|
3797
4272
|
console.log(` ${mark} ${label}`);
|
|
3798
4273
|
}
|
|
3799
4274
|
async function cmdCursor(parsed) {
|
|
3800
|
-
const cwd =
|
|
4275
|
+
const cwd = resolve9(parsed.options.dir || process.cwd());
|
|
3801
4276
|
const dry = hasFlag(parsed, "dry");
|
|
3802
4277
|
const force = hasFlag(parsed, "force") || !hasFlag(parsed, "keep");
|
|
3803
4278
|
const lib = hasFlag(parsed, "lib") || isElcrmLibPackage(cwd);
|
|
@@ -3810,24 +4285,24 @@ async function cmdCursor(parsed) {
|
|
|
3810
4285
|
];
|
|
3811
4286
|
console.log(`${dry ? "[dry] " : ""}elcrm cursor \u2192 ${cwd}/.cursor (${kind}${lib ? ", lib" : ""})`);
|
|
3812
4287
|
for (const name of ruleNames) {
|
|
3813
|
-
let body = readBundled(
|
|
4288
|
+
let body = readBundled(join20("elcrm-cursor", "rules", name));
|
|
3814
4289
|
if (kind === "server" && (name === "elcrm-server.mdc" || name === "elcrm-rpc.mdc")) {
|
|
3815
4290
|
body = body.replace("alwaysApply: false", "alwaysApply: true").replace(/^globs:.*\n/m, "");
|
|
3816
4291
|
}
|
|
3817
|
-
writeOne(
|
|
4292
|
+
writeOne(join20(cwd, ".cursor", "rules", name), body, dry, force, `.cursor/rules/${name}`);
|
|
3818
4293
|
}
|
|
3819
4294
|
const docs = docsForProject(kind, lib);
|
|
3820
4295
|
for (const name of docs) {
|
|
3821
|
-
const body = readBundled(
|
|
3822
|
-
writeOne(
|
|
4296
|
+
const body = readBundled(join20("elcrm-docs", name));
|
|
4297
|
+
writeOne(join20(cwd, ".cursor", "docs", name), body, dry, force, `.cursor/docs/${name}`);
|
|
3823
4298
|
}
|
|
3824
|
-
writeOne(
|
|
4299
|
+
writeOne(join20(cwd, "AGENTS.md"), readBundled(join20("elcrm-cursor", "AGENTS.md")), dry, force, "AGENTS.md");
|
|
3825
4300
|
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."));
|
|
3826
4301
|
}
|
|
3827
4302
|
|
|
3828
4303
|
// src/commands/doctor.ts
|
|
3829
4304
|
async function cmdDoctor(parsed) {
|
|
3830
|
-
const cwd =
|
|
4305
|
+
const cwd = resolve10(parsed.options.dir || process.cwd());
|
|
3831
4306
|
const dry = hasFlag(parsed, "dry");
|
|
3832
4307
|
const doDocs = hasFlag(parsed, "docs");
|
|
3833
4308
|
const doTest = hasFlag(parsed, "test");
|
|
@@ -3871,6 +4346,7 @@ async function cmdDoctor(parsed) {
|
|
|
3871
4346
|
}
|
|
3872
4347
|
}
|
|
3873
4348
|
const tidy = await tidyFrontProject({ cwd, pkg, dry, hacks });
|
|
4349
|
+
await doctorKitSync({ cwd, dry });
|
|
3874
4350
|
if (doDocs) {
|
|
3875
4351
|
const flags = dry ? ["dry"] : [];
|
|
3876
4352
|
const child = {
|
|
@@ -3903,7 +4379,7 @@ doctor: \u0433\u043E\u0442\u043E\u0432\u043E (${n} \u043F\u0440\u0430\u0432\u043
|
|
|
3903
4379
|
}
|
|
3904
4380
|
|
|
3905
4381
|
// src/commands/build.ts
|
|
3906
|
-
import { existsSync as
|
|
4382
|
+
import { existsSync as existsSync17 } from "fs";
|
|
3907
4383
|
|
|
3908
4384
|
// src/lib/nextVersion.ts
|
|
3909
4385
|
async function nextVersion() {
|
|
@@ -3926,9 +4402,9 @@ async function nextVersion() {
|
|
|
3926
4402
|
|
|
3927
4403
|
// src/commands/build.ts
|
|
3928
4404
|
function resolveEntrypoint() {
|
|
3929
|
-
if (
|
|
4405
|
+
if (existsSync17("./src/index.js"))
|
|
3930
4406
|
return "./src/index.js";
|
|
3931
|
-
if (
|
|
4407
|
+
if (existsSync17("./src/index.ts"))
|
|
3932
4408
|
return "./src/index.ts";
|
|
3933
4409
|
return "./src/index.js";
|
|
3934
4410
|
}
|
|
@@ -4006,22 +4482,22 @@ async function cmdUuid() {
|
|
|
4006
4482
|
}
|
|
4007
4483
|
|
|
4008
4484
|
// src/commands/postbuild.ts
|
|
4009
|
-
import { resolve as
|
|
4485
|
+
import { resolve as resolve11 } from "path";
|
|
4010
4486
|
|
|
4011
4487
|
// src/vite/postbuild.ts
|
|
4012
4488
|
import {
|
|
4013
|
-
existsSync as
|
|
4014
|
-
readdirSync as
|
|
4015
|
-
readFileSync as
|
|
4489
|
+
existsSync as existsSync18,
|
|
4490
|
+
readdirSync as readdirSync11,
|
|
4491
|
+
readFileSync as readFileSync26,
|
|
4016
4492
|
rmSync,
|
|
4017
|
-
statSync as
|
|
4018
|
-
writeFileSync as
|
|
4493
|
+
statSync as statSync9,
|
|
4494
|
+
writeFileSync as writeFileSync11
|
|
4019
4495
|
} from "fs";
|
|
4020
|
-
import { join as
|
|
4496
|
+
import { join as join22 } from "path";
|
|
4021
4497
|
|
|
4022
4498
|
// src/vite/concat-css.ts
|
|
4023
|
-
import { readdirSync as
|
|
4024
|
-
import { join as
|
|
4499
|
+
import { readdirSync as readdirSync10, readFileSync as readFileSync25, writeFileSync as writeFileSync10 } from "fs";
|
|
4500
|
+
import { join as join21 } from "path";
|
|
4025
4501
|
var SKIP_CSS = new Set([
|
|
4026
4502
|
"index.css",
|
|
4027
4503
|
"tokens.css",
|
|
@@ -4036,11 +4512,11 @@ function concatDistCss(options) {
|
|
|
4036
4512
|
outFile,
|
|
4037
4513
|
...options.skip ?? []
|
|
4038
4514
|
]);
|
|
4039
|
-
const files =
|
|
4040
|
-
const css = files.map((f) =>
|
|
4515
|
+
const files = readdirSync10(options.distDir).filter((f) => f.endsWith(".css") && !skip.has(f)).sort();
|
|
4516
|
+
const css = files.map((f) => readFileSync25(join21(options.distDir, f), "utf8")).join(`
|
|
4041
4517
|
`);
|
|
4042
|
-
const outPath =
|
|
4043
|
-
|
|
4518
|
+
const outPath = join21(options.distDir, outFile);
|
|
4519
|
+
writeFileSync10(outPath, css);
|
|
4044
4520
|
console.log(`[concat-css] ${files.length} \u0444\u0430\u0439\u043B\u043E\u0432 \u2192 ${outFile}`);
|
|
4045
4521
|
return outPath;
|
|
4046
4522
|
}
|
|
@@ -4057,19 +4533,19 @@ function postbuildLib(options) {
|
|
|
4057
4533
|
distDir: dist,
|
|
4058
4534
|
outFile: options.cssOutFile ?? "index.css"
|
|
4059
4535
|
});
|
|
4060
|
-
for (const name of
|
|
4061
|
-
const dir =
|
|
4062
|
-
if (!
|
|
4536
|
+
for (const name of readdirSync11(dist)) {
|
|
4537
|
+
const dir = join22(dist, name);
|
|
4538
|
+
if (!statSync9(dir).isDirectory())
|
|
4063
4539
|
continue;
|
|
4064
4540
|
if (keep.has(name))
|
|
4065
4541
|
continue;
|
|
4066
|
-
const impl =
|
|
4067
|
-
const nestedIndex =
|
|
4068
|
-
const flat =
|
|
4069
|
-
const src =
|
|
4542
|
+
const impl = join22(dir, `${name}.d.ts`);
|
|
4543
|
+
const nestedIndex = join22(dir, "index.d.ts");
|
|
4544
|
+
const flat = join22(dist, `${name}.d.ts`);
|
|
4545
|
+
const src = existsSync18(impl) ? impl : existsSync18(nestedIndex) ? nestedIndex : null;
|
|
4070
4546
|
if (src) {
|
|
4071
|
-
const text =
|
|
4072
|
-
|
|
4547
|
+
const text = readFileSync26(src, "utf8").replace(/from ['"]\.\.\/([^'"]+)['"]/g, `from './$1'`);
|
|
4548
|
+
writeFileSync11(flat, text);
|
|
4073
4549
|
console.log(`[postbuild] types \u2192 ${name}.d.ts`);
|
|
4074
4550
|
}
|
|
4075
4551
|
rmSync(dir, { recursive: true, force: true });
|
|
@@ -4080,7 +4556,7 @@ function postbuildLib(options) {
|
|
|
4080
4556
|
// src/commands/postbuild.ts
|
|
4081
4557
|
async function cmdPostbuild(parsed) {
|
|
4082
4558
|
const dir = parsed.options.dir || "./dist";
|
|
4083
|
-
const distDir =
|
|
4559
|
+
const distDir = resolve11(process.cwd(), dir);
|
|
4084
4560
|
postbuildLib({ distDir });
|
|
4085
4561
|
console.log(`[postbuild] \u0433\u043E\u0442\u043E\u0432\u043E: ${distDir}`);
|
|
4086
4562
|
}
|
|
@@ -4148,8 +4624,8 @@ css-sanitize: \u043F\u043E\u0447\u0438\u043D\u0435\u043D\u043E ${cleaned.length}
|
|
|
4148
4624
|
}
|
|
4149
4625
|
|
|
4150
4626
|
// src/commands/audit.ts
|
|
4151
|
-
import { existsSync as
|
|
4152
|
-
import { join as
|
|
4627
|
+
import { existsSync as existsSync19, readFileSync as readFileSync27 } from "fs";
|
|
4628
|
+
import { join as join23, relative as relative4 } from "path";
|
|
4153
4629
|
function scan(cwd) {
|
|
4154
4630
|
const out = [];
|
|
4155
4631
|
const pkg = readPackageJson(cwd);
|
|
@@ -4180,7 +4656,7 @@ function scan(cwd) {
|
|
|
4180
4656
|
}
|
|
4181
4657
|
const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r));
|
|
4182
4658
|
for (const file of files) {
|
|
4183
|
-
const text =
|
|
4659
|
+
const text = readFileSync27(file, "utf8");
|
|
4184
4660
|
const rel2 = relative4(cwd, file);
|
|
4185
4661
|
const lines = text.split(/\r?\n/);
|
|
4186
4662
|
lines.forEach((line, i) => {
|
|
@@ -4282,7 +4758,7 @@ function scan(cwd) {
|
|
|
4282
4758
|
return false;
|
|
4283
4759
|
if (/theme(-light|-dark)?\.css$/.test(f))
|
|
4284
4760
|
return false;
|
|
4285
|
-
const t =
|
|
4761
|
+
const t = readFileSync27(f, "utf8");
|
|
4286
4762
|
return t.includes("--field-border:") && t.includes("--button-secondary-bg:") && t.includes("transparent");
|
|
4287
4763
|
});
|
|
4288
4764
|
if (toolbarMarkers.length > 1) {
|
|
@@ -4293,8 +4769,8 @@ function scan(cwd) {
|
|
|
4293
4769
|
fix: "\u043E\u0431\u0449\u0438\u0439 \u043A\u043B\u0430\u0441\u0441 + theme tokens"
|
|
4294
4770
|
});
|
|
4295
4771
|
}
|
|
4296
|
-
const styleDir = ["src/style", "src/styles", "style"].map((d) =>
|
|
4297
|
-
if (styleDir && !
|
|
4772
|
+
const styleDir = ["src/style", "src/styles", "style"].map((d) => join23(cwd, d)).find(existsSync19);
|
|
4773
|
+
if (styleDir && !existsSync19(join23(styleDir, "elcrm.css"))) {
|
|
4298
4774
|
out.push({
|
|
4299
4775
|
level: "info",
|
|
4300
4776
|
code: "elcrm-css",
|
|
@@ -4302,8 +4778,8 @@ function scan(cwd) {
|
|
|
4302
4778
|
fix: "elcrm css"
|
|
4303
4779
|
});
|
|
4304
4780
|
}
|
|
4305
|
-
if (styleDir &&
|
|
4306
|
-
const elcrmCss =
|
|
4781
|
+
if (styleDir && existsSync19(join23(styleDir, "elcrm.css"))) {
|
|
4782
|
+
const elcrmCss = readFileSync27(join23(styleDir, "elcrm.css"), "utf8");
|
|
4307
4783
|
for (const m of elcrmCss.matchAll(/@import\s+["'](@elcrm\/[^"']+)["']/g)) {
|
|
4308
4784
|
const spec = m[1];
|
|
4309
4785
|
if (!resolveElcrmCssImport(spec, cwd)) {
|
|
@@ -4311,7 +4787,7 @@ function scan(cwd) {
|
|
|
4311
4787
|
level: "error",
|
|
4312
4788
|
code: "elcrm-import-missing",
|
|
4313
4789
|
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`,
|
|
4314
|
-
file: relative4(cwd,
|
|
4790
|
+
file: relative4(cwd, join23(styleDir, "elcrm.css")),
|
|
4315
4791
|
fix: "elcrm css"
|
|
4316
4792
|
});
|
|
4317
4793
|
}
|
|
@@ -4323,8 +4799,8 @@ function scan(cwd) {
|
|
|
4323
4799
|
"theme-light.css",
|
|
4324
4800
|
"theme-dark.css",
|
|
4325
4801
|
"theme.css"
|
|
4326
|
-
].map((f) =>
|
|
4327
|
-
const themeText = themeFiles.filter(
|
|
4802
|
+
].map((f) => join23(styleDir, f));
|
|
4803
|
+
const themeText = themeFiles.filter(existsSync19).map((f) => readFileSync27(f, "utf8")).join(`
|
|
4328
4804
|
`);
|
|
4329
4805
|
if (themeText && !/--popup-shadow\s*:/.test(themeText) && /--date-popup-shadow\s*:|--select-background\s*:/.test(themeText)) {
|
|
4330
4806
|
out.push({
|
|
@@ -4346,7 +4822,7 @@ function scan(cwd) {
|
|
|
4346
4822
|
for (const file of files) {
|
|
4347
4823
|
if (!file.endsWith(".css"))
|
|
4348
4824
|
continue;
|
|
4349
|
-
const text =
|
|
4825
|
+
const text = readFileSync27(file, "utf8");
|
|
4350
4826
|
const relPath = relative4(cwd, file);
|
|
4351
4827
|
const lines = text.split(/\r?\n/);
|
|
4352
4828
|
let prevNonEmpty = "";
|
|
@@ -4435,15 +4911,128 @@ ${c.cyan("\u2192")} elcrm migrate front${hasFlag(parsed, "dry") ? " --dry" : ""}
|
|
|
4435
4911
|
console.log("\u0420\u0435\u043A\u043E\u043C\u0435\u043D\u0434\u0443\u0435\u0442\u0441\u044F: elcrm css && elcrm doctor");
|
|
4436
4912
|
}
|
|
4437
4913
|
|
|
4914
|
+
// src/commands/kit.ts
|
|
4915
|
+
import { resolve as resolve12, join as join24 } from "path";
|
|
4916
|
+
function showKitHelp() {
|
|
4917
|
+
console.log(`elcrm kit \u2014 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F elUI (UIKit)
|
|
4918
|
+
|
|
4919
|
+
emit [--dir=\u2026] [--dry]
|
|
4920
|
+
dist/*.d.ts \u2192 .elcrm/kit-manifest.json + dist/kit-manifest.json
|
|
4921
|
+
\u0417\u0430\u043F\u0443\u0441\u043A\u0430\u0442\u044C \u0432 @elcrm/components | @elcrm/form \u043F\u043E\u0441\u043B\u0435 build
|
|
4922
|
+
|
|
4923
|
+
sync [--api=\u2026] [--web=\u2026] [--no-reseed] [--dry]
|
|
4924
|
+
manifest \u2192 elUI.api/src/kit/manifests/*.json
|
|
4925
|
+
\u043E\u0431\u043D\u043E\u0432\u043B\u044F\u0435\u0442 pkg-versions + elUI.web deps + kit:reseed
|
|
4926
|
+
|
|
4927
|
+
pull [--api=\u2026] [--no-reseed] [--dry]
|
|
4928
|
+
emit + sync (\u0443\u0434\u043E\u0431\u043D\u043E \u0432 postbuild)
|
|
4929
|
+
|
|
4930
|
+
config [--api=\u2026] [--web=\u2026] [--global] [--local] [--show]
|
|
4931
|
+
\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)
|
|
4932
|
+
|
|
4933
|
+
\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
|
|
4934
|
+
|
|
4935
|
+
\u041E\u0434\u0438\u043D \u0440\u0430\u0437:
|
|
4936
|
+
elcrm kit config --api=/path/to/elUI.api --web=/path/to/elUI.web --global
|
|
4937
|
+
|
|
4938
|
+
\u041F\u0440\u0438\u043C\u0435\u0440 (components):
|
|
4939
|
+
npm run build && elcrm kit pull
|
|
4940
|
+
|
|
4941
|
+
\u041F\u0440\u0438\u043C\u0435\u0440 (elUI.api \u043F\u043E\u0441\u043B\u0435 pull):
|
|
4942
|
+
bun run kit:reseed
|
|
4943
|
+
`);
|
|
4944
|
+
}
|
|
4945
|
+
async function cmdKit(parsed) {
|
|
4946
|
+
const sub = parsed.positionals[0] || "help";
|
|
4947
|
+
const cwd = resolve12(parsed.options.dir || process.cwd());
|
|
4948
|
+
const dry = hasFlag(parsed, "dry");
|
|
4949
|
+
const noReseed = hasFlag(parsed, "no-reseed");
|
|
4950
|
+
if (sub === "help" || sub === "--help") {
|
|
4951
|
+
showKitHelp();
|
|
4952
|
+
return;
|
|
4953
|
+
}
|
|
4954
|
+
if (sub === "emit") {
|
|
4955
|
+
const pkg = readPkgAt(cwd);
|
|
4956
|
+
if (!pkg?.name || !kitPkgSlug(pkg.name)) {
|
|
4957
|
+
console.error(c.red("kit emit \u2014 \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0439\u0442\u0435 \u0432 @elcrm/components \u0438\u043B\u0438 @elcrm/form"));
|
|
4958
|
+
process.exit(1);
|
|
4959
|
+
}
|
|
4960
|
+
const manifest = emitKitManifest(cwd);
|
|
4961
|
+
const paths = writeKitManifest(cwd, manifest, dry);
|
|
4962
|
+
console.log(`${dry ? "[dry] " : ""}emit: ${manifest.components.length} \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u043E\u0432`);
|
|
4963
|
+
for (const p of paths)
|
|
4964
|
+
console.log(` \u2192 ${p}`);
|
|
4965
|
+
return;
|
|
4966
|
+
}
|
|
4967
|
+
if (sub === "sync") {
|
|
4968
|
+
await syncKitManifest({
|
|
4969
|
+
cwd,
|
|
4970
|
+
apiDir: parsed.options.api,
|
|
4971
|
+
webDir: parsed.options.web,
|
|
4972
|
+
dry,
|
|
4973
|
+
reseed: !noReseed
|
|
4974
|
+
});
|
|
4975
|
+
return;
|
|
4976
|
+
}
|
|
4977
|
+
if (sub === "config") {
|
|
4978
|
+
const global = hasFlag(parsed, "global") || !hasFlag(parsed, "local");
|
|
4979
|
+
const show = hasFlag(parsed, "show") || !parsed.options.api && !parsed.options.web;
|
|
4980
|
+
if (show && !parsed.options.api && !parsed.options.web) {
|
|
4981
|
+
const saved = loadKitPathsConfig(cwd);
|
|
4982
|
+
const api = findEluiApiDir(cwd, parsed.options.api) ?? "(\u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D)";
|
|
4983
|
+
const web = findEluiWebDir(cwd, parsed.options.web) ?? "(\u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D)";
|
|
4984
|
+
console.log("elcrm kit config:");
|
|
4985
|
+
console.log(" \u0444\u0430\u0439\u043B:", global ? "~/.elcrm/kit-paths.json" : ".elcrm/kit-paths.json");
|
|
4986
|
+
console.log(" apiDir (\u0444\u0430\u0439\u043B):", saved.apiDir ?? "\u2014");
|
|
4987
|
+
console.log(" webDir (\u0444\u0430\u0439\u043B):", saved.webDir ?? "\u2014");
|
|
4988
|
+
console.log(" apiDir (resolve):", api);
|
|
4989
|
+
console.log(" webDir (resolve):", web);
|
|
4990
|
+
if (!saved.apiDir) {
|
|
4991
|
+
console.log(c.dim(`
|
|
4992
|
+
\u0417\u0430\u0434\u0430\u0442\u044C: elcrm kit config --api=\u2026 --web=\u2026 --global`));
|
|
4993
|
+
}
|
|
4994
|
+
return;
|
|
4995
|
+
}
|
|
4996
|
+
const next = saveKitPathsConfig(cwd, {
|
|
4997
|
+
...parsed.options.api ? { apiDir: parsed.options.api } : {},
|
|
4998
|
+
...parsed.options.web ? { webDir: parsed.options.web } : {}
|
|
4999
|
+
}, global);
|
|
5000
|
+
const where = global ? "~/.elcrm/kit-paths.json" : join24(cwd, ".elcrm/kit-paths.json");
|
|
5001
|
+
console.log(c.green("kit config \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D \u2192 " + where));
|
|
5002
|
+
if (next.apiDir)
|
|
5003
|
+
console.log(" apiDir:", next.apiDir);
|
|
5004
|
+
if (next.webDir)
|
|
5005
|
+
console.log(" webDir:", next.webDir);
|
|
5006
|
+
return;
|
|
5007
|
+
}
|
|
5008
|
+
if (sub === "pull") {
|
|
5009
|
+
if (!isElcrmLibPackage(cwd)) {
|
|
5010
|
+
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"));
|
|
5011
|
+
process.exit(1);
|
|
5012
|
+
}
|
|
5013
|
+
await emitAndSync({
|
|
5014
|
+
cwd,
|
|
5015
|
+
apiDir: parsed.options.api,
|
|
5016
|
+
webDir: parsed.options.web,
|
|
5017
|
+
dry,
|
|
5018
|
+
reseed: !noReseed
|
|
5019
|
+
});
|
|
5020
|
+
return;
|
|
5021
|
+
}
|
|
5022
|
+
console.error(`\u041D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430\u044F \u043F\u043E\u0434\u043A\u043E\u043C\u0430\u043D\u0434\u0430 kit: ${sub}`);
|
|
5023
|
+
showKitHelp();
|
|
5024
|
+
process.exit(1);
|
|
5025
|
+
}
|
|
5026
|
+
|
|
4438
5027
|
// src/index.ts
|
|
4439
5028
|
function cliVersion() {
|
|
4440
5029
|
const here = dirname4(fileURLToPath2(import.meta.url));
|
|
4441
5030
|
for (const p of [
|
|
4442
|
-
|
|
4443
|
-
|
|
5031
|
+
join25(here, "..", "package.json"),
|
|
5032
|
+
join25(here, "package.json")
|
|
4444
5033
|
]) {
|
|
4445
5034
|
try {
|
|
4446
|
-
const v = JSON.parse(
|
|
5035
|
+
const v = JSON.parse(readFileSync28(p, "utf8")).version;
|
|
4447
5036
|
if (typeof v === "string" && v)
|
|
4448
5037
|
return v;
|
|
4449
5038
|
} catch {}
|
|
@@ -4479,6 +5068,12 @@ function showHelp() {
|
|
|
4479
5068
|
.cursor/rules + .cursor/docs + AGENTS.md
|
|
4480
5069
|
--lib: \u0447\u0435\u043A\u043B\u0438\u0441\u0442 \u0430\u0432\u0442\u043E\u0440\u0430 @elcrm/*
|
|
4481
5070
|
|
|
5071
|
+
kit <emit|sync|pull|config> [--api=\u2026] [--web=\u2026] [--no-reseed] [--dry]
|
|
5072
|
+
config \u2014 \u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u043F\u0443\u0442\u0438 \u0432 ~/.elcrm/kit-paths.json (--global)
|
|
5073
|
+
emit \u2014 manifest \u0438\u0437 dist/*.d.ts (@elcrm/components|form)
|
|
5074
|
+
sync \u2014 manifest \u2192 elUI.api/src/kit/manifests + reseed
|
|
5075
|
+
pull \u2014 emit + sync (postbuild \u043F\u0430\u043A\u0435\u0442\u0430)
|
|
5076
|
+
|
|
4482
5077
|
migrate <name> [--dry] | migrate --list
|
|
4483
5078
|
front|ui = \u043F\u0430\u043A\u0435\u0442 \u043C\u0438\u0433\u0440\u0430\u0446\u0438\u0439 (aliases, form-native, native-html, tokens, \u2026)
|
|
4484
5079
|
\u043F\u043E \u043E\u0434\u043D\u043E\u0439: form-aliases, form-native, native-html, form-tokens, components,
|
|
@@ -4490,6 +5085,7 @@ function showHelp() {
|
|
|
4490
5085
|
\u041F\u043E\u0441\u043B\u0435 --fix \u0434\u043B\u044F imports: elcrm css
|
|
4491
5086
|
|
|
4492
5087
|
doctor [--dry] [--docs] [--test] [--hacks] [--dir=\u2026]
|
|
5088
|
+
migrate + css; \u0432 @elcrm/components|form + dist/ \u2192 kit pull
|
|
4493
5089
|
\u041D\u0430\u0432\u0435\u0434\u0435\u043D\u0438\u0435 \u043F\u043E\u0440\u044F\u0434\u043A\u0430 (\u043F\u0440\u043E\u0441\u0442\u043E \u0432\u044B\u0437\u0432\u0430\u0442\u044C). \u041F\u0440\u0435\u0432\u044C\u044E: --dry
|
|
4494
5090
|
package.json \u2192 migrate front \u2192 css. --docs / --test \u043F\u043E \u0436\u0435\u043B\u0430\u043D\u0438\u044E
|
|
4495
5091
|
|
|
@@ -4563,6 +5159,9 @@ async function main() {
|
|
|
4563
5159
|
case "cursor":
|
|
4564
5160
|
await cmdCursor(parsed);
|
|
4565
5161
|
break;
|
|
5162
|
+
case "kit":
|
|
5163
|
+
await cmdKit(parsed);
|
|
5164
|
+
break;
|
|
4566
5165
|
case "uuid":
|
|
4567
5166
|
await cmdUuid();
|
|
4568
5167
|
break;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elcrm",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "CLI @elcrm/*: doctor --fix (порядок проекта), update, css, docs, cursor, migrate",
|
|
3
|
+
"version": "1.1.21",
|
|
4
|
+
"description": "CLI @elcrm/*: doctor --fix (порядок проекта), update, css, docs, cursor, kit, migrate",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "MaSkal <dev@elcrm.online>",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"build": "bun build ./src/index.ts --outdir ./dist --target bun --format esm && bun build ./src/vite/plugin-css-scoped.ts --outfile ./dist/vite/plugin-css-scoped.js --target node --format esm --packages external && bun build ./src/vite/discover-lib.ts --outfile ./dist/vite/discover-lib.js --target node --format esm --packages external && bun build ./src/vite/concat-css.ts --outfile ./dist/vite/concat-css.js --target node --format esm --packages external && bun build ./src/vite/check-tokens.ts --outfile ./dist/vite/check-tokens.js --target node --format esm --packages external && bun build ./src/vite/postbuild.ts --outfile ./dist/vite/postbuild.js --target node --format esm --packages external && bun build ./src/vite/minify-css-vars.ts --outfile ./dist/vite/minify-css-vars.js --target node --format esm --packages external && node ./scripts/chmod-bin.mjs && node ./scripts/copy-vite-dts.mjs",
|
|
53
53
|
"dev": "bun run ./src/index.ts",
|
|
54
54
|
"elcrm": "bun run ./src/index.ts",
|
|
55
|
-
"test": "bun test src/lib/migrate src/lib/tidy.test.ts src/vite",
|
|
55
|
+
"test": "bun test src/lib/migrate src/lib/tidy.test.ts src/lib/kit src/vite",
|
|
56
56
|
"link:local": "bun run build && bun link",
|
|
57
57
|
"prepublishOnly": "bun run test && bun run build",
|
|
58
58
|
"publish:npm": "npm publish"
|