-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TODO: Console and logLevel #13
Comments
Update:
|
|
This should morph into a wider topic, which should produce the following results:
We're already parsing options that would in theory be coming from the CLI (see above) and layering them over the fallbacks (in In such a case, I'd suggest a priority as follows:
This way, a user could benefit from
To do this, the parsing of args - per the helper function(s) - should be occuring in each of the main scripts; We can just use the ESBuild config object types to map a set of of Thus, finally, given the following config: // esbuild-scripts/src/config/esbuild/getBuildOptions.ts
const buildOptions = {
publicPath: path.resolve(paths.appPublic), // points at users' '<project>/public' dir
} // <project>/esbuild.config.ts
export default = {
publicPath: path.resolve(__dirname, 'App_A', 'public'),
} # cli
$ yarn esbuild-scripts build --publicPath="./App_B/public" ... the determined Lastly! It would be great to then retain the "chained commands" from the initial ideas, and use 'options terminators' to separate args, like proposed since the beginning: This would be much easier to do, once the scripts are dealing with their own arguments. The CLI should separate the separators, and pass each group of args to the 'positional arg' at the beginning of the group: |
Diverging massively from title, but the content is fine for me, here - the title should be expanded. Found! Tailwind CLI has exactly what I was thinking of regarding atomically reading/writing to a single file... /**
* When rapidly saving files atomically a couple of situations can happen:
* - The file is missing since the external program has deleted it by the time we've gotten around to reading it from the earlier save.
* - The file is being written to by the external program by the time we're going to read it and is thus treated as busy because a lock is held.
*
* To work around this we retry reading the file a handful of times with a delay between each attempt
*
* @param {string} path
* @param {number} tries
* @returns {Promise<string | undefined>}
* @throws {Error} If the file is still missing or busy after the specified number of tries
*/
export async function readFileWithRetries(path, tries = 5) {
for (let n = 0; n <= tries; n++) {
try {
return await fs.promises.readFile(path, 'utf8')
} catch (err) {
if (n !== tries) {
if (err.code === 'ENOENT' || err.code === 'EBUSY') {
await new Promise((resolve) => setTimeout(resolve, 10))
continue
}
}
throw err
}
}
}
|
Problem:
I started the project with a rough idea of having two, seperate/distinct possible logging modes; 'verbose' & 'debug'.
Since then, I came to conclusion that we should not really designate our own specifiers, nor expose some sort of API layer to the average consumer. Why? Because we can just wrap ESBuild's API instead.
To that end, our logging should really be migrated to best align with ESBuild's logging API.
The one part the appears to be missing from their side is having those logLevels indexed. There is no such "least logging" and "most logging" in a value sense, they are instead all just string literals grouped into a Type.
We can infer some reasonable indexing from supposed "depth" of each mode, and construct our own value system as follows:
this could be much better, something like a Map would allow us to iterate through the keys... but, no big deal. I don't want to do this with an array because: I want to be deliberate about assigning values; switches are a low-cost operation; and, throwing on bad values can be much easier to debug... see, the default case matches everything besides the specified cases, doing all the required error-catching in one single line, which an array would not do
Then we can create a console (why not use the standard global one? see below) and simply check
if(logLevelValue(options.logLevel) <= 4) console.debug(x)
and so forth.Why create a console in every function, instead of using the global?
NodeJS docs:
By scoping a new console instance to the current function, we can be more sure that all sync/async activity is completed before the function returns.
Naming is important: we want to be able to strip all references to
console
in the code - a standard feature of ESBuild and of pkgroll. So, we need to over-write the globally-named console with a localnew console.Console
, which accepts the input parameterproc: NodeJS.Process
to extract an stdout/stderr to write to.The latterly part about scoped consoles has, for the most part, already been done. The exposition is important, since we're potentially running asynchronously multi-threaded child processes, which all have (the same) stdout/stderr access.
More pertinently, I need to revise the previous logging implementation to match ESBuilds', using our logging priority value switcher function from above.
It will be ideal that eventually, we should be able to use optional terminators (
--
) in between commands, so that consumers can do things like specify differing log levels for different commands.Such as:
$ yarn esbuild-scripts -- test --logLevel=debug -- build --logLevel=info -- start --logLevel=warning
(...and so forth)
The text was updated successfully, but these errors were encountered: