/**
* @file core/source.js
* @copyright @spmhome @_2025
* @author Scott Meesseman @spmeesseman
*//** */
const { apply, pick } = require("@spmhome/type-utils");
const { isWpwSourceCodeLanguage } = require("../../utils");
const { findFiles } = require("@spmhome/cmn-utils");
class WpwSourceInfo
{
/**
* @private
* @type {boolean}
*/
_autoConfig;
/**
* @private
* @type {Pick<IWpwSourceCodeConfig, "ext" | "ide" | "language">}
*/
_config;
/**
* @private
* @type {WpwSourceCodeInfo}
*/
_info;
/**
* @private
* @type {WpwSourceCodeExtension}
*/
_ext;
/**
* @private
* @type {WpwSourceCodeLanguage}
*/
_lng;
/**
* @private
* @readonly
* @type {WpwSourceCodeLanguage[]}
*/
_jsTypes = [
"javascript", "react.javascript", "expo.javascript", "reactnative"
];
/**
* @private
* @readonly
* @type {WpwSourceCodeLanguage[]}
*/
_tsTypes = [ "typescript", "react.typescript", "expo.typescript" ];
/**
* @private
* @readonly
* @type {WpwSourceCodeLanguage[]}
*/
_jstsTypes = [ "typescript-javascript", "javascript-typescript" ];
/**
* @private
* @readonly
* @type {WpwSourceCodeLanguage[]}
*/
_tsjsTypes = [ "typescript-javascript" ];
/**
* @param {WpwSourceCodeConfig} config
* @param {WpwBuild} build
*/
constructor(config, build)
{
this.build = build;
this.logger = build.logger;
this.initialConfig = apply({}, pick(config, "ext", "ide", "language"));
};
get autoConfig() { return this._autoConfig === true; }
/** @private */set autoConfig(v) { this._autoConfig = v; }
get config() { return this._config; }
get dotext() { return /** @type {WpwSourceDotExtensionApp} */(`.${this.ext}`); }
get defaultExclude() { return this._defaultExclude === true; }
/** @private */set defaultExclude(v) { this._defaultExclude = v; }
get ext() { return this._ext; };
get ide() { return this._info.ide; }
get info() { return this._info; }
get isJs() { return this._jsTypes.includes(this._lng); }
get isJsTs() { return this._jstsTypes.includes(this._lng); }
get isTs() { return this._tsTypes.includes(this._lng); }
get isTsJs() { return this._tsjsTypes.includes(this._lng); }
get language() { return this._lng; }
/**
* @param {string} lPad
*/
async init(lPad)
{
const config = this.initialConfig,
l = this.logger.write("determine language type", 1, lPad);
if (!this.build.isTranspiled)
{
this._ext = "js";
this._lng = "none";
}
else if (this.build.tsc.compilerOptions.jsx?.startsWith("react") && !this._lng.startsWith("react"))
{ this._lng = this._info.language = this._lng.includes("typescript") ? "react.typescript" : "react.javascript";
this._ext = this._info.ext = this._lng === "react.typescript" ? "tsx" : "jsx";
}
else if (!config.language || !isWpwSourceCodeLanguage(config.language))
{
const src = this.build.getSrcPath();
const o = {
cwd: src, maxDepth: 6, nodir: true,
ignore: [ "**/*.d.ts", "**/model/**", "**/types/**", "**/typings/**/*", "**/node_modules/**" ]
};
const [ js, ts, jsx, tsx ] = (
await Promise.all([
findFiles("**/*.js", o), findFiles("**/*.ts", o), findFiles("**/*.jsx", o), findFiles("**/*.tsx", o)
])
).map((f) => f.length);
l.value(" root source directory", src, 1, lPad);
l.value(" # of javascript [.js] files found", js, 2, lPad);
l.value(" # of typescript [.ts] files found", ts, 2, lPad);
l.value(" # of javascript [.jsx] files found", jsx, 2, lPad);
l.value(" # of typescript [.tsx] files found", tsx, 2, lPad);
if (js > 0)
{ if (ts === 0 && tsx === 0) {
this._ext = "js";
this._lng = jsx === 0 ? "javascript" : "react.javascript";
}
else {
this._ext = "ts";
this._lng = js >= ts ? "javascript-typescript" : "typescript-javascript";
}
}
else if (ts > 0)
{ if (jsx === 0) {
this._ext = "ts";
this._lng = tsx === 0 ? "typescript" : "react.typescript";
}
else {
this._ext = "ts";
this._lng = "typescript-javascript";
}
}
else if (jsx > tsx)
{ this._ext = "jsx";
this._lng = "react.javascript";
}
else if (tsx > jsx)
{ this._ext = "tsx";
this._lng = "react.typescript";
}
else
{ this._ext = "js";
this._lng = "javascript";
}
}
else {
this._lng = config.language;
}
if (!this._ext) {
this._ext = this.isTs || this.isTsJs ? "ts" :
(this.isJs || this.isJsTs ? "js" : (this._lng.includes("javascript") ? "jsx": "tsx"));
}
l.write(`source language set to ${this._lng } [${this._ext}]`, 1, lPad);
}
update()
{
if (this.build.tsc.compilerOptions.jsx?.startsWith("react") && !this._lng.startsWith("react"))
{ this._lng = this._info.language = this._lng.includes("typescript") ? "react.typescript" : "react.javascript";
this._ext = this._info.ext = this._lng === "react.typescript" ? "tsx" : "jsx";
}
if (!this._ext) {
this._ext = this.isTs || this.isTsJs ? "ts" :
(this.isJs || this.isJsTs ? "js" : (this._lng.includes("javascript") ? "jsx": "tsx"));
}
}
}
module.exports = WpwSourceInfo;