rads-db 3.2.37 → 3.2.39
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/config.cjs +68 -56
- package/dist/config.mjs +68 -56
- package/integrations/node.cjs +1 -1
- package/integrations/node.mjs +2 -1
- package/package.json +1 -1
package/dist/config.cjs
CHANGED
|
@@ -612,70 +612,82 @@ async function expandToDirectories(patterns) {
|
|
|
612
612
|
}
|
|
613
613
|
return dirs;
|
|
614
614
|
}
|
|
615
|
-
function
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
await fs__default.promises.mkdir(resolved, { recursive: true });
|
|
627
|
-
resolvedDirs.push(resolved);
|
|
628
|
-
}
|
|
615
|
+
async function resolveDirs(pathsArray) {
|
|
616
|
+
const resolvedDirs = [];
|
|
617
|
+
for (const p of pathsArray) {
|
|
618
|
+
if (fg__default.isDynamicPattern(p)) {
|
|
619
|
+
const matches = await fg__default(p, { onlyDirectories: true, absolute: true });
|
|
620
|
+
resolvedDirs.push(...matches);
|
|
621
|
+
} else {
|
|
622
|
+
const resolved = path__default.resolve(p);
|
|
623
|
+
if (!fs__default.existsSync(resolved))
|
|
624
|
+
await fs__default.promises.mkdir(resolved, { recursive: true });
|
|
625
|
+
resolvedDirs.push(resolved);
|
|
629
626
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
627
|
+
}
|
|
628
|
+
return resolvedDirs;
|
|
629
|
+
}
|
|
630
|
+
async function scanDirs(resolvedDirs) {
|
|
631
|
+
const entities = {};
|
|
632
|
+
const entityFilePaths = {};
|
|
633
|
+
const entityDirs = {};
|
|
634
|
+
for (const dir of resolvedDirs) {
|
|
635
|
+
const entries = await fs__default.promises.readdir(dir, { withFileTypes: true });
|
|
636
|
+
for (const entry of entries) {
|
|
637
|
+
if (!entry.isFile() || !entry.name.endsWith(".ts"))
|
|
638
|
+
continue;
|
|
639
|
+
const filePath = path__default.join(dir, entry.name);
|
|
640
|
+
const content = await fs__default.promises.readFile(filePath, "utf-8");
|
|
641
|
+
const stem = entry.name.slice(0, -3);
|
|
642
|
+
const hasEntity = content.includes("@entity");
|
|
643
|
+
if (hasEntity && entityFilePaths[stem]) {
|
|
644
|
+
throw new Error(
|
|
645
|
+
`Entity name collision: "${stem}" is defined in multiple locations:
|
|
646
646
|
${entityFilePaths[stem]}
|
|
647
647
|
${filePath}`
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
entities[stem] = content;
|
|
651
|
+
if (hasEntity) {
|
|
651
652
|
entityFilePaths[stem] = filePath;
|
|
652
653
|
entityDirs[stem] = dir;
|
|
653
654
|
}
|
|
654
655
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
);
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
if (error)
|
|
675
|
-
throw new Error(error);
|
|
676
|
-
}
|
|
677
|
-
}
|
|
656
|
+
}
|
|
657
|
+
return { entities, entityFilePaths, entityDirs };
|
|
658
|
+
}
|
|
659
|
+
async function validateEntityRules(entityFilePaths, entityDirs, entityRules) {
|
|
660
|
+
const resolvedRules = await Promise.all(
|
|
661
|
+
entityRules.map(async (rule) => {
|
|
662
|
+
const rulePaths = Array.isArray(rule.path) ? rule.path : [rule.path];
|
|
663
|
+
const dirs = await expandToDirectories(rulePaths);
|
|
664
|
+
return { rule, dirs };
|
|
665
|
+
})
|
|
666
|
+
);
|
|
667
|
+
for (const [stem, filePath] of Object.entries(entityFilePaths)) {
|
|
668
|
+
const entityDir = entityDirs[stem];
|
|
669
|
+
for (const { rule, dirs } of resolvedRules) {
|
|
670
|
+
const applies = dirs.some((d) => entityDir === d || entityDir.startsWith(d + path__default.sep));
|
|
671
|
+
if (!applies)
|
|
672
|
+
continue;
|
|
673
|
+
if (rule.namePrefix && !stem.startsWith(rule.namePrefix)) {
|
|
674
|
+
throw new Error(`Entity "${stem}" at "${filePath}" must have name prefix "${rule.namePrefix}"`);
|
|
678
675
|
}
|
|
676
|
+
if (rule.validate) {
|
|
677
|
+
const error = rule.validate(stem, filePath);
|
|
678
|
+
if (error)
|
|
679
|
+
throw new Error(error);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
function schemaFromFiles(paths, options) {
|
|
685
|
+
return async () => {
|
|
686
|
+
const pathsArray = Array.isArray(paths) ? paths : [paths];
|
|
687
|
+
const resolvedDirs = await resolveDirs(pathsArray);
|
|
688
|
+
const { entities, entityFilePaths, entityDirs } = await scanDirs(resolvedDirs);
|
|
689
|
+
if (options?.entityRules?.length) {
|
|
690
|
+
await validateEntityRules(entityFilePaths, entityDirs, options.entityRules);
|
|
679
691
|
}
|
|
680
692
|
const isSingleLiteralPath = pathsArray.length === 1 && !fg__default.isDynamicPattern(pathsArray[0]);
|
|
681
693
|
const entitiesDir = isSingleLiteralPath ? pathsArray[0] : void 0;
|
package/dist/config.mjs
CHANGED
|
@@ -603,70 +603,82 @@ async function expandToDirectories(patterns) {
|
|
|
603
603
|
}
|
|
604
604
|
return dirs;
|
|
605
605
|
}
|
|
606
|
-
function
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
await fs.promises.mkdir(resolved, { recursive: true });
|
|
618
|
-
resolvedDirs.push(resolved);
|
|
619
|
-
}
|
|
606
|
+
async function resolveDirs(pathsArray) {
|
|
607
|
+
const resolvedDirs = [];
|
|
608
|
+
for (const p of pathsArray) {
|
|
609
|
+
if (fg.isDynamicPattern(p)) {
|
|
610
|
+
const matches = await fg(p, { onlyDirectories: true, absolute: true });
|
|
611
|
+
resolvedDirs.push(...matches);
|
|
612
|
+
} else {
|
|
613
|
+
const resolved = path.resolve(p);
|
|
614
|
+
if (!fs.existsSync(resolved))
|
|
615
|
+
await fs.promises.mkdir(resolved, { recursive: true });
|
|
616
|
+
resolvedDirs.push(resolved);
|
|
620
617
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
618
|
+
}
|
|
619
|
+
return resolvedDirs;
|
|
620
|
+
}
|
|
621
|
+
async function scanDirs(resolvedDirs) {
|
|
622
|
+
const entities = {};
|
|
623
|
+
const entityFilePaths = {};
|
|
624
|
+
const entityDirs = {};
|
|
625
|
+
for (const dir of resolvedDirs) {
|
|
626
|
+
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
|
627
|
+
for (const entry of entries) {
|
|
628
|
+
if (!entry.isFile() || !entry.name.endsWith(".ts"))
|
|
629
|
+
continue;
|
|
630
|
+
const filePath = path.join(dir, entry.name);
|
|
631
|
+
const content = await fs.promises.readFile(filePath, "utf-8");
|
|
632
|
+
const stem = entry.name.slice(0, -3);
|
|
633
|
+
const hasEntity = content.includes("@entity");
|
|
634
|
+
if (hasEntity && entityFilePaths[stem]) {
|
|
635
|
+
throw new Error(
|
|
636
|
+
`Entity name collision: "${stem}" is defined in multiple locations:
|
|
637
637
|
${entityFilePaths[stem]}
|
|
638
638
|
${filePath}`
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
639
|
+
);
|
|
640
|
+
}
|
|
641
|
+
entities[stem] = content;
|
|
642
|
+
if (hasEntity) {
|
|
642
643
|
entityFilePaths[stem] = filePath;
|
|
643
644
|
entityDirs[stem] = dir;
|
|
644
645
|
}
|
|
645
646
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
);
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
if (error)
|
|
666
|
-
throw new Error(error);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
647
|
+
}
|
|
648
|
+
return { entities, entityFilePaths, entityDirs };
|
|
649
|
+
}
|
|
650
|
+
async function validateEntityRules(entityFilePaths, entityDirs, entityRules) {
|
|
651
|
+
const resolvedRules = await Promise.all(
|
|
652
|
+
entityRules.map(async (rule) => {
|
|
653
|
+
const rulePaths = Array.isArray(rule.path) ? rule.path : [rule.path];
|
|
654
|
+
const dirs = await expandToDirectories(rulePaths);
|
|
655
|
+
return { rule, dirs };
|
|
656
|
+
})
|
|
657
|
+
);
|
|
658
|
+
for (const [stem, filePath] of Object.entries(entityFilePaths)) {
|
|
659
|
+
const entityDir = entityDirs[stem];
|
|
660
|
+
for (const { rule, dirs } of resolvedRules) {
|
|
661
|
+
const applies = dirs.some((d) => entityDir === d || entityDir.startsWith(d + path.sep));
|
|
662
|
+
if (!applies)
|
|
663
|
+
continue;
|
|
664
|
+
if (rule.namePrefix && !stem.startsWith(rule.namePrefix)) {
|
|
665
|
+
throw new Error(`Entity "${stem}" at "${filePath}" must have name prefix "${rule.namePrefix}"`);
|
|
669
666
|
}
|
|
667
|
+
if (rule.validate) {
|
|
668
|
+
const error = rule.validate(stem, filePath);
|
|
669
|
+
if (error)
|
|
670
|
+
throw new Error(error);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
function schemaFromFiles(paths, options) {
|
|
676
|
+
return async () => {
|
|
677
|
+
const pathsArray = Array.isArray(paths) ? paths : [paths];
|
|
678
|
+
const resolvedDirs = await resolveDirs(pathsArray);
|
|
679
|
+
const { entities, entityFilePaths, entityDirs } = await scanDirs(resolvedDirs);
|
|
680
|
+
if (options?.entityRules?.length) {
|
|
681
|
+
await validateEntityRules(entityFilePaths, entityDirs, options.entityRules);
|
|
670
682
|
}
|
|
671
683
|
const isSingleLiteralPath = pathsArray.length === 1 && !fg.isDynamicPattern(pathsArray[0]);
|
|
672
684
|
const entitiesDir = isSingleLiteralPath ? pathsArray[0] : void 0;
|
package/integrations/node.cjs
CHANGED
|
@@ -174,7 +174,7 @@ function getEntityTypesStrFromSchema(schema) {
|
|
|
174
174
|
if (type.isExtending && schema[type.isExtending]?.fields?.[f.name]) return "";
|
|
175
175
|
let fieldTypeStr = f.type;
|
|
176
176
|
if (f.isChange) fieldTypeStr = `Change<${fieldTypeStr}>`;
|
|
177
|
-
if (f.isRelation) fieldTypeStr = `Relation<${fieldTypeStr}>`;
|
|
177
|
+
if (f.isRelation) fieldTypeStr = `Relation<${fieldTypeStr}${f.relationDenormFields?.length ? `, ${f.relationDenormFields.map(x => `'${x}'`).join(" | ")}` : ""}>`;
|
|
178
178
|
if (f.isArray) fieldTypeStr = `${fieldTypeStr}[]`;
|
|
179
179
|
const fieldStr = ` ${f.name}${f.isRequired ? "" : "?"}: ${fieldTypeStr}`;
|
|
180
180
|
const commentStr2 = f.comment ? ` /** ${f.comment} */` : "";
|
package/integrations/node.mjs
CHANGED
|
@@ -185,7 +185,8 @@ export function getEntityTypesStrFromSchema(schema) {
|
|
|
185
185
|
if (type.isExtending && schema[type.isExtending]?.fields?.[f.name]) return "";
|
|
186
186
|
let fieldTypeStr = f.type;
|
|
187
187
|
if (f.isChange) fieldTypeStr = `Change<${fieldTypeStr}>`;
|
|
188
|
-
if (f.isRelation)
|
|
188
|
+
if (f.isRelation)
|
|
189
|
+
fieldTypeStr = `Relation<${fieldTypeStr}${f.relationDenormFields?.length ? `, ${f.relationDenormFields.map((x) => `'${x}'`).join(" | ")}` : ""}>`;
|
|
189
190
|
if (f.isArray) fieldTypeStr = `${fieldTypeStr}[]`;
|
|
190
191
|
const fieldStr = ` ${f.name}${f.isRequired ? "" : "?"}: ${fieldTypeStr}`;
|
|
191
192
|
const commentStr2 = f.comment ? ` /** ${f.comment} */` : "";
|