@kosdev-code/kos-codegen-core 3.0.23 → 3.0.24
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/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/index.js +104 -14
- package/index.js.map +1 -1
- package/index.mjs +104 -14
- package/index.mjs.map +1 -1
- package/lib/generators/add-container-support/generate-add-container-support.d.ts.map +1 -1
- package/lib/generators/augment/find-model-declaration.d.ts +15 -2
- package/lib/generators/augment/find-model-declaration.d.ts.map +1 -1
- package/lib/generators/augment/resolve-model-file.d.ts +9 -0
- package/lib/generators/augment/resolve-model-file.d.ts.map +1 -1
- package/lib/generators/generate-view-model.d.ts.map +1 -1
- package/lib/generators/index.d.ts +1 -1
- package/lib/generators/index.d.ts.map +1 -1
- package/lib/generators/java-workspace.d.ts.map +1 -1
- package/package.json +2 -2
package/index.mjs
CHANGED
|
@@ -1866,36 +1866,44 @@ function generateModel(params) {
|
|
|
1866
1866
|
}
|
|
1867
1867
|
}
|
|
1868
1868
|
const DECLARATION_MARKER = "@kosModel";
|
|
1869
|
-
function
|
|
1870
|
-
const
|
|
1871
|
-
if (wanted.size === 0) return null;
|
|
1872
|
-
const matches = [];
|
|
1869
|
+
function collectModelDeclarations(codegenFs, searchRoot) {
|
|
1870
|
+
const found = [];
|
|
1873
1871
|
for (const filePath of codegenFs.listFiles(searchRoot)) {
|
|
1874
1872
|
if (!filePath.endsWith(".ts") || filePath.endsWith(".d.ts")) continue;
|
|
1875
1873
|
const content = codegenFs.read(filePath);
|
|
1876
1874
|
if (!content || !content.includes(DECLARATION_MARKER)) continue;
|
|
1877
|
-
const declared =
|
|
1878
|
-
if (declared
|
|
1875
|
+
const declared = readModelDeclaration(codegenFs, filePath);
|
|
1876
|
+
if (declared) found.push(declared);
|
|
1879
1877
|
}
|
|
1878
|
+
return found;
|
|
1879
|
+
}
|
|
1880
|
+
function findModelDeclarationFile(codegenFs, searchRoot, identifiers) {
|
|
1881
|
+
const wanted = new Set(identifiers.filter(Boolean));
|
|
1882
|
+
if (wanted.size === 0) return null;
|
|
1883
|
+
const matches = collectModelDeclarations(codegenFs, searchRoot).filter(
|
|
1884
|
+
(d) => d.typeId && wanted.has(d.typeId) || d.className && wanted.has(d.className)
|
|
1885
|
+
).map((d) => d.filePath);
|
|
1880
1886
|
if (matches.length === 0) return null;
|
|
1881
1887
|
if (matches.length > 1) {
|
|
1882
1888
|
throw new Error(
|
|
1883
|
-
`Model
|
|
1889
|
+
`Model '${[...wanted].join(
|
|
1890
|
+
"' / '"
|
|
1891
|
+
)}' is declared in more than one file:
|
|
1884
1892
|
` + matches.sort().map((c) => ` - ${c}`).join("\n") + `
|
|
1885
1893
|
Pass modelPath to pick one.`
|
|
1886
1894
|
);
|
|
1887
1895
|
}
|
|
1888
1896
|
return matches[0];
|
|
1889
1897
|
}
|
|
1890
|
-
function
|
|
1898
|
+
function readModelDeclaration(codegenFs, filePath) {
|
|
1891
1899
|
try {
|
|
1892
1900
|
return readSourceFile(codegenFs, filePath, (sf) => {
|
|
1893
1901
|
const cls = sf.getClasses().find((c) => c.getDecorator("kosModel"));
|
|
1894
1902
|
if (!cls) return void 0;
|
|
1895
1903
|
const config = decoratorConfigText(sf, cls, "kosModel");
|
|
1896
1904
|
const inner = config?.startsWith("{") ? modelTypeIdProperty(config) : config;
|
|
1897
|
-
|
|
1898
|
-
return
|
|
1905
|
+
const typeId = inner ? resolveToStringLiteral(inner.trim(), sf.getFullText()) : void 0;
|
|
1906
|
+
return { filePath, typeId, className: cls.getName() };
|
|
1899
1907
|
});
|
|
1900
1908
|
} catch {
|
|
1901
1909
|
return void 0;
|
|
@@ -1910,7 +1918,9 @@ function resolveToStringLiteral(expression, fileText) {
|
|
|
1910
1918
|
if (literal) return literal[1];
|
|
1911
1919
|
if (!/^[A-Za-z_$][\w$]*$/.test(expression)) return void 0;
|
|
1912
1920
|
const declared = fileText.match(
|
|
1913
|
-
new RegExp(
|
|
1921
|
+
new RegExp(
|
|
1922
|
+
`\\b(?:const|let|var)\\s+${expression}\\s*(?::[^=]+)?=\\s*["'\`]([^"'\`]+)["'\`]`
|
|
1923
|
+
)
|
|
1914
1924
|
);
|
|
1915
1925
|
return declared ? declared[1] : void 0;
|
|
1916
1926
|
}
|
|
@@ -1965,7 +1975,82 @@ function resolveModelFilePath(codegenFs, query, projects) {
|
|
|
1965
1975
|
if (byDeclaration) {
|
|
1966
1976
|
return { modelFilePath: byDeclaration, internal, sourceRoot };
|
|
1967
1977
|
}
|
|
1968
|
-
|
|
1978
|
+
throw new ModelFileNotFoundError(
|
|
1979
|
+
query.modelName,
|
|
1980
|
+
query.modelProject,
|
|
1981
|
+
modelFilePath,
|
|
1982
|
+
collectModelDeclarations(codegenFs, searchRoot)
|
|
1983
|
+
);
|
|
1984
|
+
}
|
|
1985
|
+
class ModelFileNotFoundError extends Error {
|
|
1986
|
+
constructor(modelName, modelProject, conventionalPath, candidates) {
|
|
1987
|
+
super(
|
|
1988
|
+
buildNotFoundMessage(
|
|
1989
|
+
modelName,
|
|
1990
|
+
modelProject,
|
|
1991
|
+
conventionalPath,
|
|
1992
|
+
candidates
|
|
1993
|
+
)
|
|
1994
|
+
);
|
|
1995
|
+
this.modelName = modelName;
|
|
1996
|
+
this.modelProject = modelProject;
|
|
1997
|
+
this.conventionalPath = conventionalPath;
|
|
1998
|
+
this.candidates = candidates;
|
|
1999
|
+
this.name = "ModelFileNotFoundError";
|
|
2000
|
+
}
|
|
2001
|
+
modelName;
|
|
2002
|
+
modelProject;
|
|
2003
|
+
conventionalPath;
|
|
2004
|
+
candidates;
|
|
2005
|
+
}
|
|
2006
|
+
function buildNotFoundMessage(modelName, modelProject, conventionalPath, candidates) {
|
|
2007
|
+
const lines = [
|
|
2008
|
+
`Model '${modelName}' not found in project '${modelProject}'.`,
|
|
2009
|
+
`Looked for ${conventionalPath}, any '*-model.ts' under the model folder, and any '@kosModel' class named or typed '${modelName}'.`
|
|
2010
|
+
];
|
|
2011
|
+
if (candidates.length === 0) {
|
|
2012
|
+
lines.push(
|
|
2013
|
+
`This project declares no '@kosModel' classes under its model folder.`
|
|
2014
|
+
);
|
|
2015
|
+
return lines.join("\n");
|
|
2016
|
+
}
|
|
2017
|
+
const ranked = [...candidates].sort(
|
|
2018
|
+
(a, b) => closeness(modelName, b) - closeness(modelName, a)
|
|
2019
|
+
);
|
|
2020
|
+
const shown = ranked.slice(0, NOT_FOUND_SUGGESTIONS);
|
|
2021
|
+
lines.push(
|
|
2022
|
+
``,
|
|
2023
|
+
`Closest of the ${candidates.length} models this project declares:`
|
|
2024
|
+
);
|
|
2025
|
+
for (const c of shown) {
|
|
2026
|
+
const names = [c.typeId, c.className].filter(Boolean).join(" | ");
|
|
2027
|
+
lines.push(` ${names || "(name unresolved)"}
|
|
2028
|
+
${c.filePath}`);
|
|
2029
|
+
}
|
|
2030
|
+
if (ranked.length > shown.length) {
|
|
2031
|
+
lines.push(` …and ${ranked.length - shown.length} more.`);
|
|
2032
|
+
}
|
|
2033
|
+
lines.push(``, `Or pass modelPath to name the file directly.`);
|
|
2034
|
+
return lines.join("\n");
|
|
2035
|
+
}
|
|
2036
|
+
const NOT_FOUND_SUGGESTIONS = 8;
|
|
2037
|
+
function closeness(wanted, candidate) {
|
|
2038
|
+
const norm = (v) => v.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
2039
|
+
const target = norm(wanted);
|
|
2040
|
+
let best = 0;
|
|
2041
|
+
for (const name of [candidate.typeId, candidate.className]) {
|
|
2042
|
+
if (!name) continue;
|
|
2043
|
+
const n = norm(name);
|
|
2044
|
+
if (n === target) return 1e3;
|
|
2045
|
+
if (n.includes(target) || target.includes(n)) {
|
|
2046
|
+
best = Math.max(best, 500 + Math.min(n.length, target.length));
|
|
2047
|
+
continue;
|
|
2048
|
+
}
|
|
2049
|
+
let i = 0;
|
|
2050
|
+
while (i < n.length && i < target.length && n[i] === target[i]) i++;
|
|
2051
|
+
best = Math.max(best, i);
|
|
2052
|
+
}
|
|
2053
|
+
return best;
|
|
1969
2054
|
}
|
|
1970
2055
|
function findModelFileByName(codegenFs, searchRoot, modelNameDashCase) {
|
|
1971
2056
|
const fileName = `${modelNameDashCase}-model.ts`;
|
|
@@ -2062,7 +2147,9 @@ function generateViewModel(codegenFs, templateDir, options, cwd, projects) {
|
|
|
2062
2147
|
logger.info(
|
|
2063
2148
|
`Generating ViewModel ${normalized.nameDashCase} in ${projectRoot}`
|
|
2064
2149
|
);
|
|
2065
|
-
const constructorParams = resolved.map(({ name, type }) =>
|
|
2150
|
+
const constructorParams = resolved.map(({ name, type }) => {
|
|
2151
|
+
return { name, type };
|
|
2152
|
+
});
|
|
2066
2153
|
generateFilesFromTemplates(codegenFs, templateDir, viewModelFolder, {
|
|
2067
2154
|
...normalized,
|
|
2068
2155
|
internal,
|
|
@@ -2122,7 +2209,9 @@ function groupImports(resolved) {
|
|
|
2122
2209
|
types.push(type);
|
|
2123
2210
|
}
|
|
2124
2211
|
}
|
|
2125
|
-
return [...byModule].map(([module, types]) =>
|
|
2212
|
+
return [...byModule].map(([module, types]) => {
|
|
2213
|
+
return { module, types };
|
|
2214
|
+
});
|
|
2126
2215
|
}
|
|
2127
2216
|
function modelBaseName(modelFilePath, modelName) {
|
|
2128
2217
|
const base = path.basename(modelFilePath);
|
|
@@ -4530,6 +4619,7 @@ export {
|
|
|
4530
4619
|
KOS_JSON_PATHS,
|
|
4531
4620
|
KosConfigBuilder,
|
|
4532
4621
|
LOCALIZED_PLUGIN_TYPES,
|
|
4622
|
+
ModelFileNotFoundError,
|
|
4533
4623
|
PLUGIN_TYPES,
|
|
4534
4624
|
PluginHandlerFactory,
|
|
4535
4625
|
TrackingFileSystem,
|