elcrm 1.1.20 → 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.
Files changed (2) hide show
  1. package/dist/index.js +265 -117
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2,8 +2,8 @@
2
2
  // @bun
3
3
 
4
4
  // src/index.ts
5
- import { readFileSync as readFileSync27 } from "fs";
6
- import { dirname as dirname4, join as join23 } from "path";
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 resolve9 } from "path";
3674
+ import { resolve as resolve10 } from "path";
3675
3675
 
3676
3676
  // src/lib/kit/doctor-kit.ts
3677
- import { existsSync as existsSync14 } from "fs";
3678
- import { join as join16, resolve as resolve6 } from "path";
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 existsSync12, readFileSync as readFileSync19 } from "fs";
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 findEluiApiDir(from) {
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 && existsSync12(join12(env, "src/kit/catalog.ts")))
3722
- return resolve3(env);
3723
- let dir = resolve3(from);
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 = join12(dir, name);
3727
- if (existsSync12(join12(candidate, "src/kit/catalog.ts")))
3819
+ const candidate = join13(dir, name);
3820
+ if (existsSync13(join13(candidate, "src/kit/catalog.ts")))
3728
3821
  return candidate;
3729
3822
  }
3730
- const parent = join12(dir, "..");
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 && readName(env) === "elui-web")
3740
- return resolve3(env);
3741
- let dir = resolve3(from);
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 = join12(dir, name);
3745
- if (readName(candidate) === "elui-web")
3846
+ const candidate = join13(dir, name);
3847
+ if (readName2(candidate) === "elui-web")
3746
3848
  return candidate;
3747
3849
  }
3748
- dir = join12(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 existsSync13, mkdirSync as mkdirSync3, readFileSync as readFileSync22, writeFileSync as writeFileSync7 } from "fs";
3765
- import { join as join15, resolve as resolve5 } from "path";
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 mkdirSync2, readFileSync as readFileSync21, writeFileSync as writeFileSync6 } from "fs";
3770
- import { join as join14, resolve as resolve4 } from "path";
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 readFileSync20, readdirSync as readdirSync8, statSync as statSync8 } from "fs";
3774
- import { basename, join as join13 } from "path";
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",
@@ -3894,10 +3996,10 @@ function scanDistComponents(distDir, importFrom) {
3894
3996
  const slug = basename(name, ".d.ts");
3895
3997
  if (SKIP_SLUGS.has(slug) || slug.includes("."))
3896
3998
  continue;
3897
- const path = join13(distDir, name);
3999
+ const path = join14(distDir, name);
3898
4000
  if (!statSync8(path).isFile())
3899
4001
  continue;
3900
- const content = readFileSync20(path, "utf8");
4002
+ const content = readFileSync21(path, "utf8");
3901
4003
  const parsed = parseComponentDts(content, slug);
3902
4004
  if (!parsed)
3903
4005
  continue;
@@ -3910,7 +4012,7 @@ function scanDistComponents(distDir, importFrom) {
3910
4012
 
3911
4013
  // src/lib/kit/emit.ts
3912
4014
  function readPkg(cwd) {
3913
- const j = JSON.parse(readFileSync21(join14(cwd, "package.json"), "utf8"));
4015
+ const j = JSON.parse(readFileSync22(join15(cwd, "package.json"), "utf8"));
3914
4016
  if (!j.name?.startsWith("@elcrm/")) {
3915
4017
  throw new Error("elcrm kit emit \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0432 npm-\u043F\u0430\u043A\u0435\u0442\u0435 @elcrm/*");
3916
4018
  }
@@ -3922,7 +4024,7 @@ function emitKitManifest(cwd) {
3922
4024
  if (!pkgSlug) {
3923
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)`);
3924
4026
  }
3925
- const distDir = join14(cwd, "dist");
4027
+ const distDir = join15(cwd, "dist");
3926
4028
  const components = scanDistComponents(distDir, pkg.name).map((c2) => ({
3927
4029
  ...c2,
3928
4030
  importFrom: pkg.name
@@ -3939,8 +4041,8 @@ function emitKitManifest(cwd) {
3939
4041
  function writeKitManifest(cwd, manifest, dry = false) {
3940
4042
  const written = [];
3941
4043
  const targets = [
3942
- join14(cwd, ".elcrm", "kit-manifest.json"),
3943
- join14(cwd, "dist", "kit-manifest.json")
4044
+ join15(cwd, ".elcrm", "kit-manifest.json"),
4045
+ join15(cwd, "dist", "kit-manifest.json")
3944
4046
  ];
3945
4047
  const body = `${JSON.stringify(manifest, null, 2)}
3946
4048
  `;
@@ -3949,20 +4051,20 @@ function writeKitManifest(cwd, manifest, dry = false) {
3949
4051
  written.push(path);
3950
4052
  continue;
3951
4053
  }
3952
- mkdirSync2(join14(path, ".."), { recursive: true });
3953
- writeFileSync6(path, body, "utf8");
4054
+ mkdirSync3(join15(path, ".."), { recursive: true });
4055
+ writeFileSync7(path, body, "utf8");
3954
4056
  written.push(path);
3955
4057
  }
3956
4058
  return written;
3957
4059
  }
3958
4060
  function readKitManifest(path) {
3959
- return JSON.parse(readFileSync21(resolve4(path), "utf8"));
4061
+ return JSON.parse(readFileSync22(resolve5(path), "utf8"));
3960
4062
  }
3961
4063
 
3962
4064
  // src/lib/kit/sync.ts
3963
4065
  function patchPkgVersions(apiDir, npmName, version, dry) {
3964
- const path = join15(apiDir, "src/kit/pkg-versions.ts");
3965
- let src = readFileSync22(path, "utf8");
4066
+ const path = join16(apiDir, "src/kit/pkg-versions.ts");
4067
+ let src = readFileSync23(path, "utf8");
3966
4068
  const re = new RegExp(`("${npmName.replace("/", "\\/")}"\\s*:\\s*")[^"]+(")`);
3967
4069
  if (!re.test(src)) {
3968
4070
  console.warn(c.yellow(` ! FALLBACK_DEPS: \u043D\u0435\u0442 ${npmName} \u0432 pkg-versions.ts`));
@@ -3972,17 +4074,17 @@ function patchPkgVersions(apiDir, npmName, version, dry) {
3972
4074
  if (next === src)
3973
4075
  return;
3974
4076
  if (!dry)
3975
- writeFileSync7(path, next, "utf8");
4077
+ writeFileSync8(path, next, "utf8");
3976
4078
  console.log(` ${dry ? "~" : c.green("+")} pkg-versions \u2192 ${npmName} ${version}`);
3977
4079
  }
3978
4080
  function patchWebDep(webDir, npmName, version, dry) {
3979
- const path = join15(webDir, "package.json");
3980
- const j = JSON.parse(readFileSync22(path, "utf8"));
4081
+ const path = join16(webDir, "package.json");
4082
+ const j = JSON.parse(readFileSync23(path, "utf8"));
3981
4083
  if (!j.dependencies?.[npmName])
3982
4084
  return;
3983
4085
  j.dependencies[npmName] = version;
3984
4086
  if (!dry)
3985
- writeFileSync7(path, `${JSON.stringify(j, null, 2)}
4087
+ writeFileSync8(path, `${JSON.stringify(j, null, 2)}
3986
4088
  `, "utf8");
3987
4089
  console.log(` ${dry ? "~" : c.green("+")} elUI.web \u2192 ${npmName}@${version}`);
3988
4090
  }
@@ -4003,31 +4105,37 @@ function runReseed(apiDir, webDir, dry) {
4003
4105
  throw new Error("kit:reseed \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0441\u044F \u0441 \u043E\u0448\u0438\u0431\u043A\u043E\u0439");
4004
4106
  }
4005
4107
  async function syncKitManifest(opts) {
4006
- const cwd = resolve5(opts.cwd);
4108
+ const cwd = resolve6(opts.cwd);
4007
4109
  const dry = opts.dry ?? false;
4008
4110
  const reseed = opts.reseed !== false;
4111
+ persistKitPathsFromOpts({
4112
+ cwd,
4113
+ apiDir: opts.apiDir,
4114
+ webDir: opts.webDir,
4115
+ dry
4116
+ });
4009
4117
  let manifest;
4010
4118
  if (opts.manifestPath) {
4011
4119
  manifest = readKitManifest(opts.manifestPath);
4012
- } else if (existsSync13(join15(cwd, ".elcrm", "kit-manifest.json"))) {
4013
- manifest = readKitManifest(join15(cwd, ".elcrm", "kit-manifest.json"));
4120
+ } else if (existsSync14(join16(cwd, ".elcrm", "kit-manifest.json"))) {
4121
+ manifest = readKitManifest(join16(cwd, ".elcrm", "kit-manifest.json"));
4014
4122
  } else {
4015
4123
  manifest = emitKitManifest(cwd);
4016
4124
  }
4017
- const apiDir = opts.apiDir ? resolve5(opts.apiDir) : findEluiApiDir(cwd);
4125
+ const apiDir = findEluiApiDir(cwd, opts.apiDir);
4018
4126
  if (!apiDir) {
4019
- throw new Error("\u041D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D elUI.api (\u0437\u0430\u0434\u0430\u0439\u0442\u0435 --api=\u2026 \u0438\u043B\u0438 ELUI_API_DIR). Manifest \u043C\u043E\u0436\u043D\u043E \u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C: elcrm kit emit");
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");
4020
4128
  }
4021
- const outDir = join15(apiDir, "src/kit/manifests");
4022
- const outFile = join15(outDir, manifestFileName(manifest.package));
4129
+ const outDir = join16(apiDir, "src/kit/manifests");
4130
+ const outFile = join16(outDir, manifestFileName(manifest.package));
4023
4131
  if (!dry) {
4024
- mkdirSync3(outDir, { recursive: true });
4025
- writeFileSync7(outFile, `${JSON.stringify(manifest, null, 2)}
4132
+ mkdirSync4(outDir, { recursive: true });
4133
+ writeFileSync8(outFile, `${JSON.stringify(manifest, null, 2)}
4026
4134
  `, "utf8");
4027
4135
  }
4028
4136
  console.log(`${dry ? "[dry] " : ""}sync \u2192 ${outFile} (${manifest.components.length} \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u043E\u0432, ${manifest.version})`);
4029
4137
  patchPkgVersions(apiDir, manifest.package, manifest.version, dry);
4030
- const webDir = opts.webDir ? resolve5(opts.webDir) : opts.patchWeb !== false ? findEluiWebDir(cwd) : null;
4138
+ const webDir = opts.patchWeb === false ? null : findEluiWebDir(cwd, opts.webDir);
4031
4139
  if (webDir)
4032
4140
  patchWebDep(webDir, manifest.package, manifest.version, dry);
4033
4141
  if (reseed)
@@ -4042,14 +4150,14 @@ async function emitAndSync(opts) {
4042
4150
 
4043
4151
  // src/lib/kit/doctor-kit.ts
4044
4152
  async function doctorKitSync(opts) {
4045
- const cwd = resolve6(opts.cwd);
4153
+ const cwd = resolve7(opts.cwd);
4046
4154
  const dry = opts.dry ?? false;
4047
4155
  if (!isElcrmLibPackage(cwd))
4048
4156
  return false;
4049
4157
  const pkg = readPkgAt(cwd);
4050
4158
  if (!pkg?.name || !kitPkgSlug(pkg.name))
4051
4159
  return false;
4052
- if (!existsSync14(join16(cwd, "dist"))) {
4160
+ if (!existsSync15(join17(cwd, "dist"))) {
4053
4161
  console.log(c.dim(`
4054
4162
  kit: \u043F\u0440\u043E\u043F\u0443\u0441\u043A \u2014 \u043D\u0435\u0442 dist/ (\u0441\u043D\u0430\u0447\u0430\u043B\u0430 npm run build)`));
4055
4163
  return false;
@@ -4061,13 +4169,13 @@ ${dry ? "[dry] " : ""}kit: sync \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442
4061
4169
  return true;
4062
4170
  } catch (err) {
4063
4171
  console.warn(c.yellow("kit: " + (err instanceof Error ? err.message : String(err))));
4064
- console.warn(c.dim(" \u0417\u0430\u0434\u0430\u0439\u0442\u0435 ELUI_API_DIR=\u2026 \u0438\u043B\u0438 elcrm kit pull --api=\u2026/elUI.api"));
4172
+ console.warn(c.dim(" \u0417\u0430\u0434\u0430\u0439\u0442\u0435 elcrm kit config --api=\u2026 --web=\u2026 --global"));
4065
4173
  return false;
4066
4174
  }
4067
4175
  }
4068
4176
 
4069
4177
  // src/commands/docs.ts
4070
- import { join as join18, resolve as resolve7 } from "path";
4178
+ import { join as join19, resolve as resolve8 } from "path";
4071
4179
 
4072
4180
  // src/lib/elcrmDocsCatalog.ts
4073
4181
  var ALL_ELCRM_DOCS = [
@@ -4101,33 +4209,33 @@ function docsForProject(kind, lib) {
4101
4209
 
4102
4210
  // src/lib/scaffoldFiles.ts
4103
4211
  import {
4104
- existsSync as existsSync15,
4105
- mkdirSync as mkdirSync4,
4212
+ existsSync as existsSync16,
4213
+ mkdirSync as mkdirSync5,
4106
4214
  readdirSync as readdirSync9,
4107
- readFileSync as readFileSync23,
4108
- writeFileSync as writeFileSync8
4215
+ readFileSync as readFileSync24,
4216
+ writeFileSync as writeFileSync9
4109
4217
  } from "fs";
4110
- import { dirname as dirname3, join as join17 } from "path";
4218
+ import { dirname as dirname3, join as join18 } from "path";
4111
4219
  function writeScaffoldFile(dest, body, opts) {
4112
4220
  if (opts.dry)
4113
4221
  return "dry";
4114
- if (!opts.force && existsSync15(dest))
4222
+ if (!opts.force && existsSync16(dest))
4115
4223
  return "skip";
4116
- mkdirSync4(dirname3(dest), { recursive: true });
4117
- writeFileSync8(dest, body, "utf8");
4224
+ mkdirSync5(dirname3(dest), { recursive: true });
4225
+ writeFileSync9(dest, body, "utf8");
4118
4226
  return "write";
4119
4227
  }
4120
4228
  function readBundled(relPath) {
4121
- const full = join17(packageRoot(), "templates", relPath);
4122
- if (!existsSync15(full)) {
4229
+ const full = join18(packageRoot(), "templates", relPath);
4230
+ if (!existsSync16(full)) {
4123
4231
  throw new Error(`\u0428\u0430\u0431\u043B\u043E\u043D \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D: ${relPath}`);
4124
4232
  }
4125
- return readFileSync23(full, "utf8");
4233
+ return readFileSync24(full, "utf8");
4126
4234
  }
4127
4235
 
4128
4236
  // src/commands/docs.ts
4129
4237
  async function cmdDocs(parsed) {
4130
- const cwd = resolve7(parsed.options.dir || process.cwd());
4238
+ const cwd = resolve8(parsed.options.dir || process.cwd());
4131
4239
  const dry = hasFlag(parsed, "dry");
4132
4240
  const force = hasFlag(parsed, "force") || !hasFlag(parsed, "keep");
4133
4241
  const lib = hasFlag(parsed, "lib") || isElcrmLibPackage(cwd);
@@ -4135,8 +4243,8 @@ async function cmdDocs(parsed) {
4135
4243
  const names = docsForProject(kind, lib);
4136
4244
  console.log(`${dry ? "[dry] " : ""}elcrm docs \u2192 ${cwd}/docs (${kind}${lib ? ", lib" : ""})`);
4137
4245
  for (const name of names) {
4138
- const body = readBundled(join18("elcrm-docs", name));
4139
- const dest = join18(cwd, "docs", name);
4246
+ const body = readBundled(join19("elcrm-docs", name));
4247
+ const dest = join19(cwd, "docs", name);
4140
4248
  const action = writeScaffoldFile(dest, body, { dry, force });
4141
4249
  const mark = action === "write" ? c.green("+") : action === "skip" ? c.gray("=") : c.cyan("~");
4142
4250
  console.log(` ${mark} docs/${name}`);
@@ -4148,7 +4256,7 @@ async function cmdDocs(parsed) {
4148
4256
  }
4149
4257
 
4150
4258
  // src/commands/cursor.ts
4151
- import { join as join19, resolve as resolve8 } from "path";
4259
+ import { join as join20, resolve as resolve9 } from "path";
4152
4260
  var ALWAYS = ["elcrm.mdc", "elcrm-packages.mdc", "elcrm-jsdoc.mdc"];
4153
4261
  var UI = [
4154
4262
  "elcrm-ui.mdc",
@@ -4164,7 +4272,7 @@ function writeOne(dest, body, dry, force, label) {
4164
4272
  console.log(` ${mark} ${label}`);
4165
4273
  }
4166
4274
  async function cmdCursor(parsed) {
4167
- const cwd = resolve8(parsed.options.dir || process.cwd());
4275
+ const cwd = resolve9(parsed.options.dir || process.cwd());
4168
4276
  const dry = hasFlag(parsed, "dry");
4169
4277
  const force = hasFlag(parsed, "force") || !hasFlag(parsed, "keep");
4170
4278
  const lib = hasFlag(parsed, "lib") || isElcrmLibPackage(cwd);
@@ -4177,24 +4285,24 @@ async function cmdCursor(parsed) {
4177
4285
  ];
4178
4286
  console.log(`${dry ? "[dry] " : ""}elcrm cursor \u2192 ${cwd}/.cursor (${kind}${lib ? ", lib" : ""})`);
4179
4287
  for (const name of ruleNames) {
4180
- let body = readBundled(join19("elcrm-cursor", "rules", name));
4288
+ let body = readBundled(join20("elcrm-cursor", "rules", name));
4181
4289
  if (kind === "server" && (name === "elcrm-server.mdc" || name === "elcrm-rpc.mdc")) {
4182
4290
  body = body.replace("alwaysApply: false", "alwaysApply: true").replace(/^globs:.*\n/m, "");
4183
4291
  }
4184
- writeOne(join19(cwd, ".cursor", "rules", name), body, dry, force, `.cursor/rules/${name}`);
4292
+ writeOne(join20(cwd, ".cursor", "rules", name), body, dry, force, `.cursor/rules/${name}`);
4185
4293
  }
4186
4294
  const docs = docsForProject(kind, lib);
4187
4295
  for (const name of docs) {
4188
- const body = readBundled(join19("elcrm-docs", name));
4189
- writeOne(join19(cwd, ".cursor", "docs", name), body, dry, force, `.cursor/docs/${name}`);
4296
+ const body = readBundled(join20("elcrm-docs", name));
4297
+ writeOne(join20(cwd, ".cursor", "docs", name), body, dry, force, `.cursor/docs/${name}`);
4190
4298
  }
4191
- writeOne(join19(cwd, "AGENTS.md"), readBundled(join19("elcrm-cursor", "AGENTS.md")), dry, force, "AGENTS.md");
4299
+ writeOne(join20(cwd, "AGENTS.md"), readBundled(join20("elcrm-cursor", "AGENTS.md")), dry, force, "AGENTS.md");
4192
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."));
4193
4301
  }
4194
4302
 
4195
4303
  // src/commands/doctor.ts
4196
4304
  async function cmdDoctor(parsed) {
4197
- const cwd = resolve9(parsed.options.dir || process.cwd());
4305
+ const cwd = resolve10(parsed.options.dir || process.cwd());
4198
4306
  const dry = hasFlag(parsed, "dry");
4199
4307
  const doDocs = hasFlag(parsed, "docs");
4200
4308
  const doTest = hasFlag(parsed, "test");
@@ -4271,7 +4379,7 @@ doctor: \u0433\u043E\u0442\u043E\u0432\u043E (${n} \u043F\u0440\u0430\u0432\u043
4271
4379
  }
4272
4380
 
4273
4381
  // src/commands/build.ts
4274
- import { existsSync as existsSync16 } from "fs";
4382
+ import { existsSync as existsSync17 } from "fs";
4275
4383
 
4276
4384
  // src/lib/nextVersion.ts
4277
4385
  async function nextVersion() {
@@ -4294,9 +4402,9 @@ async function nextVersion() {
4294
4402
 
4295
4403
  // src/commands/build.ts
4296
4404
  function resolveEntrypoint() {
4297
- if (existsSync16("./src/index.js"))
4405
+ if (existsSync17("./src/index.js"))
4298
4406
  return "./src/index.js";
4299
- if (existsSync16("./src/index.ts"))
4407
+ if (existsSync17("./src/index.ts"))
4300
4408
  return "./src/index.ts";
4301
4409
  return "./src/index.js";
4302
4410
  }
@@ -4374,22 +4482,22 @@ async function cmdUuid() {
4374
4482
  }
4375
4483
 
4376
4484
  // src/commands/postbuild.ts
4377
- import { resolve as resolve10 } from "path";
4485
+ import { resolve as resolve11 } from "path";
4378
4486
 
4379
4487
  // src/vite/postbuild.ts
4380
4488
  import {
4381
- existsSync as existsSync17,
4489
+ existsSync as existsSync18,
4382
4490
  readdirSync as readdirSync11,
4383
- readFileSync as readFileSync25,
4491
+ readFileSync as readFileSync26,
4384
4492
  rmSync,
4385
4493
  statSync as statSync9,
4386
- writeFileSync as writeFileSync10
4494
+ writeFileSync as writeFileSync11
4387
4495
  } from "fs";
4388
- import { join as join21 } from "path";
4496
+ import { join as join22 } from "path";
4389
4497
 
4390
4498
  // src/vite/concat-css.ts
4391
- import { readdirSync as readdirSync10, readFileSync as readFileSync24, writeFileSync as writeFileSync9 } from "fs";
4392
- import { join as join20 } from "path";
4499
+ import { readdirSync as readdirSync10, readFileSync as readFileSync25, writeFileSync as writeFileSync10 } from "fs";
4500
+ import { join as join21 } from "path";
4393
4501
  var SKIP_CSS = new Set([
4394
4502
  "index.css",
4395
4503
  "tokens.css",
@@ -4405,10 +4513,10 @@ function concatDistCss(options) {
4405
4513
  ...options.skip ?? []
4406
4514
  ]);
4407
4515
  const files = readdirSync10(options.distDir).filter((f) => f.endsWith(".css") && !skip.has(f)).sort();
4408
- const css = files.map((f) => readFileSync24(join20(options.distDir, f), "utf8")).join(`
4516
+ const css = files.map((f) => readFileSync25(join21(options.distDir, f), "utf8")).join(`
4409
4517
  `);
4410
- const outPath = join20(options.distDir, outFile);
4411
- writeFileSync9(outPath, css);
4518
+ const outPath = join21(options.distDir, outFile);
4519
+ writeFileSync10(outPath, css);
4412
4520
  console.log(`[concat-css] ${files.length} \u0444\u0430\u0439\u043B\u043E\u0432 \u2192 ${outFile}`);
4413
4521
  return outPath;
4414
4522
  }
@@ -4426,18 +4534,18 @@ function postbuildLib(options) {
4426
4534
  outFile: options.cssOutFile ?? "index.css"
4427
4535
  });
4428
4536
  for (const name of readdirSync11(dist)) {
4429
- const dir = join21(dist, name);
4537
+ const dir = join22(dist, name);
4430
4538
  if (!statSync9(dir).isDirectory())
4431
4539
  continue;
4432
4540
  if (keep.has(name))
4433
4541
  continue;
4434
- const impl = join21(dir, `${name}.d.ts`);
4435
- const nestedIndex = join21(dir, "index.d.ts");
4436
- const flat = join21(dist, `${name}.d.ts`);
4437
- const src = existsSync17(impl) ? impl : existsSync17(nestedIndex) ? nestedIndex : null;
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;
4438
4546
  if (src) {
4439
- const text = readFileSync25(src, "utf8").replace(/from ['"]\.\.\/([^'"]+)['"]/g, `from './$1'`);
4440
- writeFileSync10(flat, text);
4547
+ const text = readFileSync26(src, "utf8").replace(/from ['"]\.\.\/([^'"]+)['"]/g, `from './$1'`);
4548
+ writeFileSync11(flat, text);
4441
4549
  console.log(`[postbuild] types \u2192 ${name}.d.ts`);
4442
4550
  }
4443
4551
  rmSync(dir, { recursive: true, force: true });
@@ -4448,7 +4556,7 @@ function postbuildLib(options) {
4448
4556
  // src/commands/postbuild.ts
4449
4557
  async function cmdPostbuild(parsed) {
4450
4558
  const dir = parsed.options.dir || "./dist";
4451
- const distDir = resolve10(process.cwd(), dir);
4559
+ const distDir = resolve11(process.cwd(), dir);
4452
4560
  postbuildLib({ distDir });
4453
4561
  console.log(`[postbuild] \u0433\u043E\u0442\u043E\u0432\u043E: ${distDir}`);
4454
4562
  }
@@ -4516,8 +4624,8 @@ css-sanitize: \u043F\u043E\u0447\u0438\u043D\u0435\u043D\u043E ${cleaned.length}
4516
4624
  }
4517
4625
 
4518
4626
  // src/commands/audit.ts
4519
- import { existsSync as existsSync18, readFileSync as readFileSync26 } from "fs";
4520
- import { join as join22, relative as relative4 } from "path";
4627
+ import { existsSync as existsSync19, readFileSync as readFileSync27 } from "fs";
4628
+ import { join as join23, relative as relative4 } from "path";
4521
4629
  function scan(cwd) {
4522
4630
  const out = [];
4523
4631
  const pkg = readPackageJson(cwd);
@@ -4548,7 +4656,7 @@ function scan(cwd) {
4548
4656
  }
4549
4657
  const files = projectCodeRoots(cwd).flatMap((r) => walkCodeFiles(r));
4550
4658
  for (const file of files) {
4551
- const text = readFileSync26(file, "utf8");
4659
+ const text = readFileSync27(file, "utf8");
4552
4660
  const rel2 = relative4(cwd, file);
4553
4661
  const lines = text.split(/\r?\n/);
4554
4662
  lines.forEach((line, i) => {
@@ -4650,7 +4758,7 @@ function scan(cwd) {
4650
4758
  return false;
4651
4759
  if (/theme(-light|-dark)?\.css$/.test(f))
4652
4760
  return false;
4653
- const t = readFileSync26(f, "utf8");
4761
+ const t = readFileSync27(f, "utf8");
4654
4762
  return t.includes("--field-border:") && t.includes("--button-secondary-bg:") && t.includes("transparent");
4655
4763
  });
4656
4764
  if (toolbarMarkers.length > 1) {
@@ -4661,8 +4769,8 @@ function scan(cwd) {
4661
4769
  fix: "\u043E\u0431\u0449\u0438\u0439 \u043A\u043B\u0430\u0441\u0441 + theme tokens"
4662
4770
  });
4663
4771
  }
4664
- const styleDir = ["src/style", "src/styles", "style"].map((d) => join22(cwd, d)).find(existsSync18);
4665
- if (styleDir && !existsSync18(join22(styleDir, "elcrm.css"))) {
4772
+ const styleDir = ["src/style", "src/styles", "style"].map((d) => join23(cwd, d)).find(existsSync19);
4773
+ if (styleDir && !existsSync19(join23(styleDir, "elcrm.css"))) {
4666
4774
  out.push({
4667
4775
  level: "info",
4668
4776
  code: "elcrm-css",
@@ -4670,8 +4778,8 @@ function scan(cwd) {
4670
4778
  fix: "elcrm css"
4671
4779
  });
4672
4780
  }
4673
- if (styleDir && existsSync18(join22(styleDir, "elcrm.css"))) {
4674
- const elcrmCss = readFileSync26(join22(styleDir, "elcrm.css"), "utf8");
4781
+ if (styleDir && existsSync19(join23(styleDir, "elcrm.css"))) {
4782
+ const elcrmCss = readFileSync27(join23(styleDir, "elcrm.css"), "utf8");
4675
4783
  for (const m of elcrmCss.matchAll(/@import\s+["'](@elcrm\/[^"']+)["']/g)) {
4676
4784
  const spec = m[1];
4677
4785
  if (!resolveElcrmCssImport(spec, cwd)) {
@@ -4679,7 +4787,7 @@ function scan(cwd) {
4679
4787
  level: "error",
4680
4788
  code: "elcrm-import-missing",
4681
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`,
4682
- file: relative4(cwd, join22(styleDir, "elcrm.css")),
4790
+ file: relative4(cwd, join23(styleDir, "elcrm.css")),
4683
4791
  fix: "elcrm css"
4684
4792
  });
4685
4793
  }
@@ -4691,8 +4799,8 @@ function scan(cwd) {
4691
4799
  "theme-light.css",
4692
4800
  "theme-dark.css",
4693
4801
  "theme.css"
4694
- ].map((f) => join22(styleDir, f));
4695
- const themeText = themeFiles.filter(existsSync18).map((f) => readFileSync26(f, "utf8")).join(`
4802
+ ].map((f) => join23(styleDir, f));
4803
+ const themeText = themeFiles.filter(existsSync19).map((f) => readFileSync27(f, "utf8")).join(`
4696
4804
  `);
4697
4805
  if (themeText && !/--popup-shadow\s*:/.test(themeText) && /--date-popup-shadow\s*:|--select-background\s*:/.test(themeText)) {
4698
4806
  out.push({
@@ -4714,7 +4822,7 @@ function scan(cwd) {
4714
4822
  for (const file of files) {
4715
4823
  if (!file.endsWith(".css"))
4716
4824
  continue;
4717
- const text = readFileSync26(file, "utf8");
4825
+ const text = readFileSync27(file, "utf8");
4718
4826
  const relPath = relative4(cwd, file);
4719
4827
  const lines = text.split(/\r?\n/);
4720
4828
  let prevNonEmpty = "";
@@ -4804,7 +4912,7 @@ ${c.cyan("\u2192")} elcrm migrate front${hasFlag(parsed, "dry") ? " --dry" : ""}
4804
4912
  }
4805
4913
 
4806
4914
  // src/commands/kit.ts
4807
- import { resolve as resolve11 } from "path";
4915
+ import { resolve as resolve12, join as join24 } from "path";
4808
4916
  function showKitHelp() {
4809
4917
  console.log(`elcrm kit \u2014 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F elUI (UIKit)
4810
4918
 
@@ -4819,7 +4927,13 @@ function showKitHelp() {
4819
4927
  pull [--api=\u2026] [--no-reseed] [--dry]
4820
4928
  emit + sync (\u0443\u0434\u043E\u0431\u043D\u043E \u0432 postbuild)
4821
4929
 
4822
- \u041F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u044B\u0435: ELUI_API_DIR, ELUI_WEB_DIR
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
4823
4937
 
4824
4938
  \u041F\u0440\u0438\u043C\u0435\u0440 (components):
4825
4939
  npm run build && elcrm kit pull
@@ -4830,7 +4944,7 @@ function showKitHelp() {
4830
4944
  }
4831
4945
  async function cmdKit(parsed) {
4832
4946
  const sub = parsed.positionals[0] || "help";
4833
- const cwd = resolve11(parsed.options.dir || process.cwd());
4947
+ const cwd = resolve12(parsed.options.dir || process.cwd());
4834
4948
  const dry = hasFlag(parsed, "dry");
4835
4949
  const noReseed = hasFlag(parsed, "no-reseed");
4836
4950
  if (sub === "help" || sub === "--help") {
@@ -4860,6 +4974,37 @@ async function cmdKit(parsed) {
4860
4974
  });
4861
4975
  return;
4862
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
+ }
4863
5008
  if (sub === "pull") {
4864
5009
  if (!isElcrmLibPackage(cwd)) {
4865
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"));
@@ -4867,6 +5012,8 @@ async function cmdKit(parsed) {
4867
5012
  }
4868
5013
  await emitAndSync({
4869
5014
  cwd,
5015
+ apiDir: parsed.options.api,
5016
+ webDir: parsed.options.web,
4870
5017
  dry,
4871
5018
  reseed: !noReseed
4872
5019
  });
@@ -4881,11 +5028,11 @@ async function cmdKit(parsed) {
4881
5028
  function cliVersion() {
4882
5029
  const here = dirname4(fileURLToPath2(import.meta.url));
4883
5030
  for (const p of [
4884
- join23(here, "..", "package.json"),
4885
- join23(here, "package.json")
5031
+ join25(here, "..", "package.json"),
5032
+ join25(here, "package.json")
4886
5033
  ]) {
4887
5034
  try {
4888
- const v = JSON.parse(readFileSync27(p, "utf8")).version;
5035
+ const v = JSON.parse(readFileSync28(p, "utf8")).version;
4889
5036
  if (typeof v === "string" && v)
4890
5037
  return v;
4891
5038
  } catch {}
@@ -4921,7 +5068,8 @@ function showHelp() {
4921
5068
  .cursor/rules + .cursor/docs + AGENTS.md
4922
5069
  --lib: \u0447\u0435\u043A\u043B\u0438\u0441\u0442 \u0430\u0432\u0442\u043E\u0440\u0430 @elcrm/*
4923
5070
 
4924
- kit <emit|sync|pull> [--api=\u2026] [--web=\u2026] [--no-reseed] [--dry]
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)
4925
5073
  emit \u2014 manifest \u0438\u0437 dist/*.d.ts (@elcrm/components|form)
4926
5074
  sync \u2014 manifest \u2192 elUI.api/src/kit/manifests + reseed
4927
5075
  pull \u2014 emit + sync (postbuild \u043F\u0430\u043A\u0435\u0442\u0430)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "elcrm",
3
- "version": "1.1.20",
3
+ "version": "1.1.21",
4
4
  "description": "CLI @elcrm/*: doctor --fix (порядок проекта), update, css, docs, cursor, kit, migrate",
5
5
  "type": "module",
6
6
  "license": "MIT",