@coopenomics/factory 2025.7.1 → 2025.7.2
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.cjs +80 -50
- package/dist/index.mjs +80 -50
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -2916,7 +2916,7 @@ class PDFService {
|
|
|
2916
2916
|
|
|
2917
2917
|
const name = "@coopenomics/factory";
|
|
2918
2918
|
const type = "module";
|
|
2919
|
-
const version = "2025.7.
|
|
2919
|
+
const version = "2025.7.2";
|
|
2920
2920
|
const packageManager = "pnpm@9.0.6";
|
|
2921
2921
|
const description = "";
|
|
2922
2922
|
const author = "Alex Ant <chairman.voskhod@gmail.com>";
|
|
@@ -2959,14 +2959,15 @@ const scripts = {
|
|
|
2959
2959
|
prepublishOnly: "nr build",
|
|
2960
2960
|
release: "bumpp && npm publish",
|
|
2961
2961
|
test: "vitest --dir test --testTimeout=240000 --exclude documents --watch=false",
|
|
2962
|
-
typecheck: "tsc --noEmit"
|
|
2962
|
+
typecheck: "tsc --noEmit",
|
|
2963
|
+
"setup-indexes": "tsx scripts/setup-indexes.ts"
|
|
2963
2964
|
};
|
|
2964
2965
|
const dependencies = {
|
|
2965
2966
|
ajv: "^8.13.0",
|
|
2966
2967
|
"ajv-formats": "^3.0.1",
|
|
2967
2968
|
"ajv-i18n": "^4.2.0",
|
|
2968
2969
|
axios: "^1.7.2",
|
|
2969
|
-
cooptypes: "2025.7.
|
|
2970
|
+
cooptypes: "2025.7.2",
|
|
2970
2971
|
dotenv: "^16.4.5",
|
|
2971
2972
|
"eosjs-ecc": "^4.0.7",
|
|
2972
2973
|
handlebars: "^4.7.8",
|
|
@@ -3007,7 +3008,7 @@ const pnpm = {
|
|
|
3007
3008
|
"vite@>=5.1.0 <=5.1.6": ">=5.1.7"
|
|
3008
3009
|
}
|
|
3009
3010
|
};
|
|
3010
|
-
const gitHead = "
|
|
3011
|
+
const gitHead = "305864c1ed125be304a3b4fa9749ac6743dd5571";
|
|
3011
3012
|
const packageJson = {
|
|
3012
3013
|
name: name,
|
|
3013
3014
|
type: type,
|
|
@@ -4685,28 +4686,40 @@ class SearchService {
|
|
|
4685
4686
|
__publicField$1(this, "storage");
|
|
4686
4687
|
this.storage = storage;
|
|
4687
4688
|
}
|
|
4689
|
+
// Экранирование специальных символов регулярных выражений
|
|
4690
|
+
escapeRegex(text) {
|
|
4691
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4692
|
+
}
|
|
4688
4693
|
async search(query) {
|
|
4689
4694
|
if (!query || query.trim().length === 0) {
|
|
4690
4695
|
return [];
|
|
4691
4696
|
}
|
|
4692
4697
|
const results = [];
|
|
4693
4698
|
const trimmedQuery = query.trim();
|
|
4694
|
-
|
|
4699
|
+
console.log(`[SearchService] \u041F\u043E\u0438\u0441\u043A \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: "${trimmedQuery}"`);
|
|
4700
|
+
const escapedQuery = this.escapeRegex(trimmedQuery);
|
|
4695
4701
|
const queryWords = trimmedQuery.split(/\s+/).filter((word) => word.length > 0);
|
|
4696
4702
|
try {
|
|
4697
|
-
|
|
4703
|
+
console.log(`[SearchService] \u041F\u043E\u0438\u0441\u043A \u0432 individuals...`);
|
|
4704
|
+
const individualResults = await this.searchIndividuals(escapedQuery, queryWords, trimmedQuery);
|
|
4705
|
+
console.log(`[SearchService] \u041D\u0430\u0439\u0434\u0435\u043D\u043E individuals: ${individualResults.length}`);
|
|
4698
4706
|
results.push(...individualResults);
|
|
4699
|
-
|
|
4707
|
+
console.log(`[SearchService] \u041F\u043E\u0438\u0441\u043A \u0432 entrepreneurs...`);
|
|
4708
|
+
const entrepreneurResults = await this.searchEntrepreneurs(escapedQuery, queryWords, trimmedQuery);
|
|
4709
|
+
console.log(`[SearchService] \u041D\u0430\u0439\u0434\u0435\u043D\u043E entrepreneurs: ${entrepreneurResults.length}`);
|
|
4700
4710
|
results.push(...entrepreneurResults);
|
|
4701
|
-
|
|
4711
|
+
console.log(`[SearchService] \u041F\u043E\u0438\u0441\u043A \u0432 organizations...`);
|
|
4712
|
+
const organizationResults = await this.searchOrganizations(escapedQuery);
|
|
4713
|
+
console.log(`[SearchService] \u041D\u0430\u0439\u0434\u0435\u043D\u043E organizations: ${organizationResults.length}`);
|
|
4702
4714
|
results.push(...organizationResults);
|
|
4715
|
+
console.log(`[SearchService] \u041E\u0431\u0449\u0435\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u043E\u0432: ${results.length}`);
|
|
4703
4716
|
return results.slice(0, 10);
|
|
4704
4717
|
} catch (error) {
|
|
4705
|
-
console.error("
|
|
4718
|
+
console.error("[SearchService] \u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u043F\u043E\u0438\u0441\u043A\u0435:", error);
|
|
4706
4719
|
return [];
|
|
4707
4720
|
}
|
|
4708
4721
|
}
|
|
4709
|
-
async searchIndividuals(
|
|
4722
|
+
async searchIndividuals(regexPattern, queryWords, originalQuery) {
|
|
4710
4723
|
const individualModel = new Individual(this.storage);
|
|
4711
4724
|
const results = [];
|
|
4712
4725
|
let filter;
|
|
@@ -4715,16 +4728,16 @@ class SearchService {
|
|
|
4715
4728
|
deleted: false,
|
|
4716
4729
|
$or: [
|
|
4717
4730
|
// Поиск по отдельным полям
|
|
4718
|
-
{ first_name: { $regex:
|
|
4719
|
-
{ last_name: { $regex:
|
|
4720
|
-
{ middle_name: { $regex:
|
|
4731
|
+
{ first_name: { $regex: regexPattern, $options: "i" } },
|
|
4732
|
+
{ last_name: { $regex: regexPattern, $options: "i" } },
|
|
4733
|
+
{ middle_name: { $regex: regexPattern, $options: "i" } },
|
|
4721
4734
|
// Поиск по полному ФИО (все слова должны быть найдены)
|
|
4722
4735
|
{
|
|
4723
4736
|
$and: queryWords.map((word) => ({
|
|
4724
4737
|
$or: [
|
|
4725
|
-
{ first_name: { $regex:
|
|
4726
|
-
{ last_name: { $regex:
|
|
4727
|
-
{ middle_name: { $regex:
|
|
4738
|
+
{ first_name: { $regex: this.escapeRegex(word), $options: "i" } },
|
|
4739
|
+
{ last_name: { $regex: this.escapeRegex(word), $options: "i" } },
|
|
4740
|
+
{ middle_name: { $regex: this.escapeRegex(word), $options: "i" } }
|
|
4728
4741
|
]
|
|
4729
4742
|
}))
|
|
4730
4743
|
}
|
|
@@ -4734,22 +4747,30 @@ class SearchService {
|
|
|
4734
4747
|
filter = {
|
|
4735
4748
|
deleted: false,
|
|
4736
4749
|
$or: [
|
|
4737
|
-
{ first_name: { $regex:
|
|
4738
|
-
{ last_name: { $regex:
|
|
4739
|
-
{ middle_name: { $regex:
|
|
4750
|
+
{ first_name: { $regex: regexPattern, $options: "i" } },
|
|
4751
|
+
{ last_name: { $regex: regexPattern, $options: "i" } },
|
|
4752
|
+
{ middle_name: { $regex: regexPattern, $options: "i" } }
|
|
4740
4753
|
]
|
|
4741
4754
|
};
|
|
4742
4755
|
}
|
|
4756
|
+
console.log(`[SearchService] \u0424\u0438\u043B\u044C\u0442\u0440 \u0434\u043B\u044F individuals:`, JSON.stringify(filter, null, 2));
|
|
4743
4757
|
const individuals = await individualModel.getMany(filter);
|
|
4758
|
+
console.log(`[SearchService] \u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u043F\u043E\u0438\u0441\u043A\u0430 individuals:`, {
|
|
4759
|
+
total: individuals.totalResults,
|
|
4760
|
+
found: individuals.results.length,
|
|
4761
|
+
query: originalQuery,
|
|
4762
|
+
names: individuals.results.map((ind) => `${ind.last_name} ${ind.first_name} ${ind.middle_name || ""} (deleted: ${ind.deleted || false})`)
|
|
4763
|
+
});
|
|
4744
4764
|
for (const individual of individuals.results) {
|
|
4745
4765
|
const highlightedFields = [];
|
|
4746
|
-
|
|
4766
|
+
const testRegex = new RegExp(regexPattern, "i");
|
|
4767
|
+
if (individual.first_name && testRegex.test(individual.first_name))
|
|
4747
4768
|
highlightedFields.push("first_name");
|
|
4748
|
-
if (
|
|
4769
|
+
if (individual.last_name && testRegex.test(individual.last_name))
|
|
4749
4770
|
highlightedFields.push("last_name");
|
|
4750
|
-
if (
|
|
4771
|
+
if (individual.middle_name && testRegex.test(individual.middle_name))
|
|
4751
4772
|
highlightedFields.push("middle_name");
|
|
4752
|
-
const fullName = `${individual.last_name} ${individual.first_name} ${individual.middle_name}`.trim();
|
|
4773
|
+
const fullName = `${individual.last_name || ""} ${individual.first_name || ""} ${individual.middle_name || ""}`.trim();
|
|
4753
4774
|
if (this.matchesFullName(fullName, queryWords)) {
|
|
4754
4775
|
highlightedFields.push("full_name");
|
|
4755
4776
|
}
|
|
@@ -4761,7 +4782,7 @@ class SearchService {
|
|
|
4761
4782
|
}
|
|
4762
4783
|
return results;
|
|
4763
4784
|
}
|
|
4764
|
-
async searchEntrepreneurs(
|
|
4785
|
+
async searchEntrepreneurs(regexPattern, queryWords, originalQuery) {
|
|
4765
4786
|
const entrepreneurModel = new Entrepreneur(this.storage);
|
|
4766
4787
|
const results = [];
|
|
4767
4788
|
let filter;
|
|
@@ -4770,18 +4791,18 @@ class SearchService {
|
|
|
4770
4791
|
deleted: false,
|
|
4771
4792
|
$or: [
|
|
4772
4793
|
// Поиск по отдельным полям
|
|
4773
|
-
{ first_name: { $regex:
|
|
4774
|
-
{ last_name: { $regex:
|
|
4775
|
-
{ middle_name: { $regex:
|
|
4776
|
-
{ "details.inn": { $regex:
|
|
4777
|
-
{ "details.ogrn": { $regex:
|
|
4794
|
+
{ first_name: { $regex: regexPattern, $options: "i" } },
|
|
4795
|
+
{ last_name: { $regex: regexPattern, $options: "i" } },
|
|
4796
|
+
{ middle_name: { $regex: regexPattern, $options: "i" } },
|
|
4797
|
+
{ "details.inn": { $regex: regexPattern, $options: "i" } },
|
|
4798
|
+
{ "details.ogrn": { $regex: regexPattern, $options: "i" } },
|
|
4778
4799
|
// Поиск по полному ФИО
|
|
4779
4800
|
{
|
|
4780
4801
|
$and: queryWords.map((word) => ({
|
|
4781
4802
|
$or: [
|
|
4782
|
-
{ first_name: { $regex:
|
|
4783
|
-
{ last_name: { $regex:
|
|
4784
|
-
{ middle_name: { $regex:
|
|
4803
|
+
{ first_name: { $regex: this.escapeRegex(word), $options: "i" } },
|
|
4804
|
+
{ last_name: { $regex: this.escapeRegex(word), $options: "i" } },
|
|
4805
|
+
{ middle_name: { $regex: this.escapeRegex(word), $options: "i" } }
|
|
4785
4806
|
]
|
|
4786
4807
|
}))
|
|
4787
4808
|
}
|
|
@@ -4791,28 +4812,36 @@ class SearchService {
|
|
|
4791
4812
|
filter = {
|
|
4792
4813
|
deleted: false,
|
|
4793
4814
|
$or: [
|
|
4794
|
-
{ first_name: { $regex:
|
|
4795
|
-
{ last_name: { $regex:
|
|
4796
|
-
{ middle_name: { $regex:
|
|
4797
|
-
{ "details.inn": { $regex:
|
|
4798
|
-
{ "details.ogrn": { $regex:
|
|
4815
|
+
{ first_name: { $regex: regexPattern, $options: "i" } },
|
|
4816
|
+
{ last_name: { $regex: regexPattern, $options: "i" } },
|
|
4817
|
+
{ middle_name: { $regex: regexPattern, $options: "i" } },
|
|
4818
|
+
{ "details.inn": { $regex: regexPattern, $options: "i" } },
|
|
4819
|
+
{ "details.ogrn": { $regex: regexPattern, $options: "i" } }
|
|
4799
4820
|
]
|
|
4800
4821
|
};
|
|
4801
4822
|
}
|
|
4823
|
+
console.log(`[SearchService] \u0424\u0438\u043B\u044C\u0442\u0440 \u0434\u043B\u044F entrepreneurs:`, JSON.stringify(filter, null, 2));
|
|
4802
4824
|
const entrepreneurs = await entrepreneurModel.getMany(filter);
|
|
4825
|
+
console.log(`[SearchService] \u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u043F\u043E\u0438\u0441\u043A\u0430 entrepreneurs:`, {
|
|
4826
|
+
total: entrepreneurs.totalResults,
|
|
4827
|
+
found: entrepreneurs.results.length,
|
|
4828
|
+
query: originalQuery,
|
|
4829
|
+
names: entrepreneurs.results.map((ent) => `${ent.last_name} ${ent.first_name} ${ent.middle_name || ""} (deleted: ${ent.deleted || false})`)
|
|
4830
|
+
});
|
|
4803
4831
|
for (const entrepreneur of entrepreneurs.results) {
|
|
4804
4832
|
const highlightedFields = [];
|
|
4805
|
-
|
|
4833
|
+
const testRegex = new RegExp(regexPattern, "i");
|
|
4834
|
+
if (entrepreneur.first_name && testRegex.test(entrepreneur.first_name))
|
|
4806
4835
|
highlightedFields.push("first_name");
|
|
4807
|
-
if (
|
|
4836
|
+
if (entrepreneur.last_name && testRegex.test(entrepreneur.last_name))
|
|
4808
4837
|
highlightedFields.push("last_name");
|
|
4809
|
-
if (
|
|
4838
|
+
if (entrepreneur.middle_name && testRegex.test(entrepreneur.middle_name))
|
|
4810
4839
|
highlightedFields.push("middle_name");
|
|
4811
|
-
if (entrepreneur.details?.inn &&
|
|
4840
|
+
if (entrepreneur.details?.inn && testRegex.test(entrepreneur.details.inn))
|
|
4812
4841
|
highlightedFields.push("details.inn");
|
|
4813
|
-
if (entrepreneur.details?.ogrn &&
|
|
4842
|
+
if (entrepreneur.details?.ogrn && testRegex.test(entrepreneur.details.ogrn))
|
|
4814
4843
|
highlightedFields.push("details.ogrn");
|
|
4815
|
-
const fullName = `${entrepreneur.last_name} ${entrepreneur.first_name} ${entrepreneur.middle_name}`.trim();
|
|
4844
|
+
const fullName = `${entrepreneur.last_name || ""} ${entrepreneur.first_name || ""} ${entrepreneur.middle_name || ""}`.trim();
|
|
4816
4845
|
if (this.matchesFullName(fullName, queryWords)) {
|
|
4817
4846
|
highlightedFields.push("full_name");
|
|
4818
4847
|
}
|
|
@@ -4824,24 +4853,25 @@ class SearchService {
|
|
|
4824
4853
|
}
|
|
4825
4854
|
return results;
|
|
4826
4855
|
}
|
|
4827
|
-
async searchOrganizations(
|
|
4856
|
+
async searchOrganizations(regexPattern) {
|
|
4828
4857
|
const organizationModel = new Organization(this.storage);
|
|
4829
4858
|
const results = [];
|
|
4830
4859
|
const organizations = await organizationModel.getMany({
|
|
4831
4860
|
deleted: false,
|
|
4832
4861
|
$or: [
|
|
4833
|
-
{ short_name: { $regex:
|
|
4834
|
-
{ "details.inn": { $regex:
|
|
4835
|
-
{ "details.ogrn": { $regex:
|
|
4862
|
+
{ short_name: { $regex: regexPattern, $options: "i" } },
|
|
4863
|
+
{ "details.inn": { $regex: regexPattern, $options: "i" } },
|
|
4864
|
+
{ "details.ogrn": { $regex: regexPattern, $options: "i" } }
|
|
4836
4865
|
]
|
|
4837
4866
|
});
|
|
4838
4867
|
for (const organization of organizations.results) {
|
|
4839
4868
|
const highlightedFields = [];
|
|
4840
|
-
|
|
4869
|
+
const testRegex = new RegExp(regexPattern, "i");
|
|
4870
|
+
if (testRegex.test(organization.short_name))
|
|
4841
4871
|
highlightedFields.push("short_name");
|
|
4842
|
-
if (organization.details?.inn &&
|
|
4872
|
+
if (organization.details?.inn && testRegex.test(organization.details.inn))
|
|
4843
4873
|
highlightedFields.push("details.inn");
|
|
4844
|
-
if (organization.details?.ogrn &&
|
|
4874
|
+
if (organization.details?.ogrn && testRegex.test(organization.details.ogrn))
|
|
4845
4875
|
highlightedFields.push("details.ogrn");
|
|
4846
4876
|
results.push({
|
|
4847
4877
|
type: "organization",
|
package/dist/index.mjs
CHANGED
|
@@ -2903,7 +2903,7 @@ class PDFService {
|
|
|
2903
2903
|
|
|
2904
2904
|
const name = "@coopenomics/factory";
|
|
2905
2905
|
const type = "module";
|
|
2906
|
-
const version = "2025.7.
|
|
2906
|
+
const version = "2025.7.2";
|
|
2907
2907
|
const packageManager = "pnpm@9.0.6";
|
|
2908
2908
|
const description = "";
|
|
2909
2909
|
const author = "Alex Ant <chairman.voskhod@gmail.com>";
|
|
@@ -2946,14 +2946,15 @@ const scripts = {
|
|
|
2946
2946
|
prepublishOnly: "nr build",
|
|
2947
2947
|
release: "bumpp && npm publish",
|
|
2948
2948
|
test: "vitest --dir test --testTimeout=240000 --exclude documents --watch=false",
|
|
2949
|
-
typecheck: "tsc --noEmit"
|
|
2949
|
+
typecheck: "tsc --noEmit",
|
|
2950
|
+
"setup-indexes": "tsx scripts/setup-indexes.ts"
|
|
2950
2951
|
};
|
|
2951
2952
|
const dependencies = {
|
|
2952
2953
|
ajv: "^8.13.0",
|
|
2953
2954
|
"ajv-formats": "^3.0.1",
|
|
2954
2955
|
"ajv-i18n": "^4.2.0",
|
|
2955
2956
|
axios: "^1.7.2",
|
|
2956
|
-
cooptypes: "2025.7.
|
|
2957
|
+
cooptypes: "2025.7.2",
|
|
2957
2958
|
dotenv: "^16.4.5",
|
|
2958
2959
|
"eosjs-ecc": "^4.0.7",
|
|
2959
2960
|
handlebars: "^4.7.8",
|
|
@@ -2994,7 +2995,7 @@ const pnpm = {
|
|
|
2994
2995
|
"vite@>=5.1.0 <=5.1.6": ">=5.1.7"
|
|
2995
2996
|
}
|
|
2996
2997
|
};
|
|
2997
|
-
const gitHead = "
|
|
2998
|
+
const gitHead = "305864c1ed125be304a3b4fa9749ac6743dd5571";
|
|
2998
2999
|
const packageJson = {
|
|
2999
3000
|
name: name,
|
|
3000
3001
|
type: type,
|
|
@@ -4672,28 +4673,40 @@ class SearchService {
|
|
|
4672
4673
|
__publicField$1(this, "storage");
|
|
4673
4674
|
this.storage = storage;
|
|
4674
4675
|
}
|
|
4676
|
+
// Экранирование специальных символов регулярных выражений
|
|
4677
|
+
escapeRegex(text) {
|
|
4678
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4679
|
+
}
|
|
4675
4680
|
async search(query) {
|
|
4676
4681
|
if (!query || query.trim().length === 0) {
|
|
4677
4682
|
return [];
|
|
4678
4683
|
}
|
|
4679
4684
|
const results = [];
|
|
4680
4685
|
const trimmedQuery = query.trim();
|
|
4681
|
-
|
|
4686
|
+
console.log(`[SearchService] \u041F\u043E\u0438\u0441\u043A \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: "${trimmedQuery}"`);
|
|
4687
|
+
const escapedQuery = this.escapeRegex(trimmedQuery);
|
|
4682
4688
|
const queryWords = trimmedQuery.split(/\s+/).filter((word) => word.length > 0);
|
|
4683
4689
|
try {
|
|
4684
|
-
|
|
4690
|
+
console.log(`[SearchService] \u041F\u043E\u0438\u0441\u043A \u0432 individuals...`);
|
|
4691
|
+
const individualResults = await this.searchIndividuals(escapedQuery, queryWords, trimmedQuery);
|
|
4692
|
+
console.log(`[SearchService] \u041D\u0430\u0439\u0434\u0435\u043D\u043E individuals: ${individualResults.length}`);
|
|
4685
4693
|
results.push(...individualResults);
|
|
4686
|
-
|
|
4694
|
+
console.log(`[SearchService] \u041F\u043E\u0438\u0441\u043A \u0432 entrepreneurs...`);
|
|
4695
|
+
const entrepreneurResults = await this.searchEntrepreneurs(escapedQuery, queryWords, trimmedQuery);
|
|
4696
|
+
console.log(`[SearchService] \u041D\u0430\u0439\u0434\u0435\u043D\u043E entrepreneurs: ${entrepreneurResults.length}`);
|
|
4687
4697
|
results.push(...entrepreneurResults);
|
|
4688
|
-
|
|
4698
|
+
console.log(`[SearchService] \u041F\u043E\u0438\u0441\u043A \u0432 organizations...`);
|
|
4699
|
+
const organizationResults = await this.searchOrganizations(escapedQuery);
|
|
4700
|
+
console.log(`[SearchService] \u041D\u0430\u0439\u0434\u0435\u043D\u043E organizations: ${organizationResults.length}`);
|
|
4689
4701
|
results.push(...organizationResults);
|
|
4702
|
+
console.log(`[SearchService] \u041E\u0431\u0449\u0435\u0435 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u043E\u0432: ${results.length}`);
|
|
4690
4703
|
return results.slice(0, 10);
|
|
4691
4704
|
} catch (error) {
|
|
4692
|
-
console.error("
|
|
4705
|
+
console.error("[SearchService] \u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u043F\u043E\u0438\u0441\u043A\u0435:", error);
|
|
4693
4706
|
return [];
|
|
4694
4707
|
}
|
|
4695
4708
|
}
|
|
4696
|
-
async searchIndividuals(
|
|
4709
|
+
async searchIndividuals(regexPattern, queryWords, originalQuery) {
|
|
4697
4710
|
const individualModel = new Individual(this.storage);
|
|
4698
4711
|
const results = [];
|
|
4699
4712
|
let filter;
|
|
@@ -4702,16 +4715,16 @@ class SearchService {
|
|
|
4702
4715
|
deleted: false,
|
|
4703
4716
|
$or: [
|
|
4704
4717
|
// Поиск по отдельным полям
|
|
4705
|
-
{ first_name: { $regex:
|
|
4706
|
-
{ last_name: { $regex:
|
|
4707
|
-
{ middle_name: { $regex:
|
|
4718
|
+
{ first_name: { $regex: regexPattern, $options: "i" } },
|
|
4719
|
+
{ last_name: { $regex: regexPattern, $options: "i" } },
|
|
4720
|
+
{ middle_name: { $regex: regexPattern, $options: "i" } },
|
|
4708
4721
|
// Поиск по полному ФИО (все слова должны быть найдены)
|
|
4709
4722
|
{
|
|
4710
4723
|
$and: queryWords.map((word) => ({
|
|
4711
4724
|
$or: [
|
|
4712
|
-
{ first_name: { $regex:
|
|
4713
|
-
{ last_name: { $regex:
|
|
4714
|
-
{ middle_name: { $regex:
|
|
4725
|
+
{ first_name: { $regex: this.escapeRegex(word), $options: "i" } },
|
|
4726
|
+
{ last_name: { $regex: this.escapeRegex(word), $options: "i" } },
|
|
4727
|
+
{ middle_name: { $regex: this.escapeRegex(word), $options: "i" } }
|
|
4715
4728
|
]
|
|
4716
4729
|
}))
|
|
4717
4730
|
}
|
|
@@ -4721,22 +4734,30 @@ class SearchService {
|
|
|
4721
4734
|
filter = {
|
|
4722
4735
|
deleted: false,
|
|
4723
4736
|
$or: [
|
|
4724
|
-
{ first_name: { $regex:
|
|
4725
|
-
{ last_name: { $regex:
|
|
4726
|
-
{ middle_name: { $regex:
|
|
4737
|
+
{ first_name: { $regex: regexPattern, $options: "i" } },
|
|
4738
|
+
{ last_name: { $regex: regexPattern, $options: "i" } },
|
|
4739
|
+
{ middle_name: { $regex: regexPattern, $options: "i" } }
|
|
4727
4740
|
]
|
|
4728
4741
|
};
|
|
4729
4742
|
}
|
|
4743
|
+
console.log(`[SearchService] \u0424\u0438\u043B\u044C\u0442\u0440 \u0434\u043B\u044F individuals:`, JSON.stringify(filter, null, 2));
|
|
4730
4744
|
const individuals = await individualModel.getMany(filter);
|
|
4745
|
+
console.log(`[SearchService] \u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u043F\u043E\u0438\u0441\u043A\u0430 individuals:`, {
|
|
4746
|
+
total: individuals.totalResults,
|
|
4747
|
+
found: individuals.results.length,
|
|
4748
|
+
query: originalQuery,
|
|
4749
|
+
names: individuals.results.map((ind) => `${ind.last_name} ${ind.first_name} ${ind.middle_name || ""} (deleted: ${ind.deleted || false})`)
|
|
4750
|
+
});
|
|
4731
4751
|
for (const individual of individuals.results) {
|
|
4732
4752
|
const highlightedFields = [];
|
|
4733
|
-
|
|
4753
|
+
const testRegex = new RegExp(regexPattern, "i");
|
|
4754
|
+
if (individual.first_name && testRegex.test(individual.first_name))
|
|
4734
4755
|
highlightedFields.push("first_name");
|
|
4735
|
-
if (
|
|
4756
|
+
if (individual.last_name && testRegex.test(individual.last_name))
|
|
4736
4757
|
highlightedFields.push("last_name");
|
|
4737
|
-
if (
|
|
4758
|
+
if (individual.middle_name && testRegex.test(individual.middle_name))
|
|
4738
4759
|
highlightedFields.push("middle_name");
|
|
4739
|
-
const fullName = `${individual.last_name} ${individual.first_name} ${individual.middle_name}`.trim();
|
|
4760
|
+
const fullName = `${individual.last_name || ""} ${individual.first_name || ""} ${individual.middle_name || ""}`.trim();
|
|
4740
4761
|
if (this.matchesFullName(fullName, queryWords)) {
|
|
4741
4762
|
highlightedFields.push("full_name");
|
|
4742
4763
|
}
|
|
@@ -4748,7 +4769,7 @@ class SearchService {
|
|
|
4748
4769
|
}
|
|
4749
4770
|
return results;
|
|
4750
4771
|
}
|
|
4751
|
-
async searchEntrepreneurs(
|
|
4772
|
+
async searchEntrepreneurs(regexPattern, queryWords, originalQuery) {
|
|
4752
4773
|
const entrepreneurModel = new Entrepreneur(this.storage);
|
|
4753
4774
|
const results = [];
|
|
4754
4775
|
let filter;
|
|
@@ -4757,18 +4778,18 @@ class SearchService {
|
|
|
4757
4778
|
deleted: false,
|
|
4758
4779
|
$or: [
|
|
4759
4780
|
// Поиск по отдельным полям
|
|
4760
|
-
{ first_name: { $regex:
|
|
4761
|
-
{ last_name: { $regex:
|
|
4762
|
-
{ middle_name: { $regex:
|
|
4763
|
-
{ "details.inn": { $regex:
|
|
4764
|
-
{ "details.ogrn": { $regex:
|
|
4781
|
+
{ first_name: { $regex: regexPattern, $options: "i" } },
|
|
4782
|
+
{ last_name: { $regex: regexPattern, $options: "i" } },
|
|
4783
|
+
{ middle_name: { $regex: regexPattern, $options: "i" } },
|
|
4784
|
+
{ "details.inn": { $regex: regexPattern, $options: "i" } },
|
|
4785
|
+
{ "details.ogrn": { $regex: regexPattern, $options: "i" } },
|
|
4765
4786
|
// Поиск по полному ФИО
|
|
4766
4787
|
{
|
|
4767
4788
|
$and: queryWords.map((word) => ({
|
|
4768
4789
|
$or: [
|
|
4769
|
-
{ first_name: { $regex:
|
|
4770
|
-
{ last_name: { $regex:
|
|
4771
|
-
{ middle_name: { $regex:
|
|
4790
|
+
{ first_name: { $regex: this.escapeRegex(word), $options: "i" } },
|
|
4791
|
+
{ last_name: { $regex: this.escapeRegex(word), $options: "i" } },
|
|
4792
|
+
{ middle_name: { $regex: this.escapeRegex(word), $options: "i" } }
|
|
4772
4793
|
]
|
|
4773
4794
|
}))
|
|
4774
4795
|
}
|
|
@@ -4778,28 +4799,36 @@ class SearchService {
|
|
|
4778
4799
|
filter = {
|
|
4779
4800
|
deleted: false,
|
|
4780
4801
|
$or: [
|
|
4781
|
-
{ first_name: { $regex:
|
|
4782
|
-
{ last_name: { $regex:
|
|
4783
|
-
{ middle_name: { $regex:
|
|
4784
|
-
{ "details.inn": { $regex:
|
|
4785
|
-
{ "details.ogrn": { $regex:
|
|
4802
|
+
{ first_name: { $regex: regexPattern, $options: "i" } },
|
|
4803
|
+
{ last_name: { $regex: regexPattern, $options: "i" } },
|
|
4804
|
+
{ middle_name: { $regex: regexPattern, $options: "i" } },
|
|
4805
|
+
{ "details.inn": { $regex: regexPattern, $options: "i" } },
|
|
4806
|
+
{ "details.ogrn": { $regex: regexPattern, $options: "i" } }
|
|
4786
4807
|
]
|
|
4787
4808
|
};
|
|
4788
4809
|
}
|
|
4810
|
+
console.log(`[SearchService] \u0424\u0438\u043B\u044C\u0442\u0440 \u0434\u043B\u044F entrepreneurs:`, JSON.stringify(filter, null, 2));
|
|
4789
4811
|
const entrepreneurs = await entrepreneurModel.getMany(filter);
|
|
4812
|
+
console.log(`[SearchService] \u0420\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u043F\u043E\u0438\u0441\u043A\u0430 entrepreneurs:`, {
|
|
4813
|
+
total: entrepreneurs.totalResults,
|
|
4814
|
+
found: entrepreneurs.results.length,
|
|
4815
|
+
query: originalQuery,
|
|
4816
|
+
names: entrepreneurs.results.map((ent) => `${ent.last_name} ${ent.first_name} ${ent.middle_name || ""} (deleted: ${ent.deleted || false})`)
|
|
4817
|
+
});
|
|
4790
4818
|
for (const entrepreneur of entrepreneurs.results) {
|
|
4791
4819
|
const highlightedFields = [];
|
|
4792
|
-
|
|
4820
|
+
const testRegex = new RegExp(regexPattern, "i");
|
|
4821
|
+
if (entrepreneur.first_name && testRegex.test(entrepreneur.first_name))
|
|
4793
4822
|
highlightedFields.push("first_name");
|
|
4794
|
-
if (
|
|
4823
|
+
if (entrepreneur.last_name && testRegex.test(entrepreneur.last_name))
|
|
4795
4824
|
highlightedFields.push("last_name");
|
|
4796
|
-
if (
|
|
4825
|
+
if (entrepreneur.middle_name && testRegex.test(entrepreneur.middle_name))
|
|
4797
4826
|
highlightedFields.push("middle_name");
|
|
4798
|
-
if (entrepreneur.details?.inn &&
|
|
4827
|
+
if (entrepreneur.details?.inn && testRegex.test(entrepreneur.details.inn))
|
|
4799
4828
|
highlightedFields.push("details.inn");
|
|
4800
|
-
if (entrepreneur.details?.ogrn &&
|
|
4829
|
+
if (entrepreneur.details?.ogrn && testRegex.test(entrepreneur.details.ogrn))
|
|
4801
4830
|
highlightedFields.push("details.ogrn");
|
|
4802
|
-
const fullName = `${entrepreneur.last_name} ${entrepreneur.first_name} ${entrepreneur.middle_name}`.trim();
|
|
4831
|
+
const fullName = `${entrepreneur.last_name || ""} ${entrepreneur.first_name || ""} ${entrepreneur.middle_name || ""}`.trim();
|
|
4803
4832
|
if (this.matchesFullName(fullName, queryWords)) {
|
|
4804
4833
|
highlightedFields.push("full_name");
|
|
4805
4834
|
}
|
|
@@ -4811,24 +4840,25 @@ class SearchService {
|
|
|
4811
4840
|
}
|
|
4812
4841
|
return results;
|
|
4813
4842
|
}
|
|
4814
|
-
async searchOrganizations(
|
|
4843
|
+
async searchOrganizations(regexPattern) {
|
|
4815
4844
|
const organizationModel = new Organization(this.storage);
|
|
4816
4845
|
const results = [];
|
|
4817
4846
|
const organizations = await organizationModel.getMany({
|
|
4818
4847
|
deleted: false,
|
|
4819
4848
|
$or: [
|
|
4820
|
-
{ short_name: { $regex:
|
|
4821
|
-
{ "details.inn": { $regex:
|
|
4822
|
-
{ "details.ogrn": { $regex:
|
|
4849
|
+
{ short_name: { $regex: regexPattern, $options: "i" } },
|
|
4850
|
+
{ "details.inn": { $regex: regexPattern, $options: "i" } },
|
|
4851
|
+
{ "details.ogrn": { $regex: regexPattern, $options: "i" } }
|
|
4823
4852
|
]
|
|
4824
4853
|
});
|
|
4825
4854
|
for (const organization of organizations.results) {
|
|
4826
4855
|
const highlightedFields = [];
|
|
4827
|
-
|
|
4856
|
+
const testRegex = new RegExp(regexPattern, "i");
|
|
4857
|
+
if (testRegex.test(organization.short_name))
|
|
4828
4858
|
highlightedFields.push("short_name");
|
|
4829
|
-
if (organization.details?.inn &&
|
|
4859
|
+
if (organization.details?.inn && testRegex.test(organization.details.inn))
|
|
4830
4860
|
highlightedFields.push("details.inn");
|
|
4831
|
-
if (organization.details?.ogrn &&
|
|
4861
|
+
if (organization.details?.ogrn && testRegex.test(organization.details.ogrn))
|
|
4832
4862
|
highlightedFields.push("details.ogrn");
|
|
4833
4863
|
results.push({
|
|
4834
4864
|
type: "organization",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coopenomics/factory",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2025.7.
|
|
4
|
+
"version": "2025.7.2",
|
|
5
5
|
"packageManager": "pnpm@9.0.6",
|
|
6
6
|
"description": "",
|
|
7
7
|
"author": "Alex Ant <chairman.voskhod@gmail.com>",
|
|
@@ -43,14 +43,15 @@
|
|
|
43
43
|
"prepublishOnly": "nr build",
|
|
44
44
|
"release": "bumpp && npm publish",
|
|
45
45
|
"test": "vitest --dir test --testTimeout=240000 --exclude documents --watch=false",
|
|
46
|
-
"typecheck": "tsc --noEmit"
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"setup-indexes": "tsx scripts/setup-indexes.ts"
|
|
47
48
|
},
|
|
48
49
|
"dependencies": {
|
|
49
50
|
"ajv": "^8.13.0",
|
|
50
51
|
"ajv-formats": "^3.0.1",
|
|
51
52
|
"ajv-i18n": "^4.2.0",
|
|
52
53
|
"axios": "^1.7.2",
|
|
53
|
-
"cooptypes": "2025.7.
|
|
54
|
+
"cooptypes": "2025.7.2",
|
|
54
55
|
"dotenv": "^16.4.5",
|
|
55
56
|
"eosjs-ecc": "^4.0.7",
|
|
56
57
|
"handlebars": "^4.7.8",
|
|
@@ -91,5 +92,5 @@
|
|
|
91
92
|
"vite@>=5.1.0 <=5.1.6": ">=5.1.7"
|
|
92
93
|
}
|
|
93
94
|
},
|
|
94
|
-
"gitHead": "
|
|
95
|
+
"gitHead": "305864c1ed125be304a3b4fa9749ac6743dd5571"
|
|
95
96
|
}
|