Open panoply opened 2 months ago
I've been using 11ty.ts
for a bit now and it has been so helpful! I think the defineConfig
approach would be a great change, and it isn't unfamiliar to developers these days - projects like Cypress, Playright, Solid, Vitest, Astro, Drizzle, Nuxt, Rsbuild, Vite, etc all use the same defineConfig
or similar helper.
For the record I do think the pattern you’ve shown here is better than what we have now!
I’d love to simplify this on the docs: https://www.11ty.dev/docs/config/#type-definitions
How can we best (and in the most simple way) make something like this happen?
import { defineConfig } from "@11ty/eleventy";
module.exports = defineConfig((eleventyConfig) {
});
Is it possible using TypeScript JSDoc comments or do we need .d.ts
as noted here https://github.com/11ty/eleventy/issues/3097#issuecomment-2256860341
I’m also happy to link to the 11ty.ts
from our TypeScript docs too, feel free to PR it here: https://www.11ty.dev/docs/languages/typescript/#using-a-typescript-configuration-file
Ideally, you'd want use a declaration opposed to relying upon jsdoc annotation typings. The reason for this is because there are restrictions apparent and underlying limitations with jsdoc type enhancements. Typically you'll find that jsdoc annotation typings are leveraged for internal reference whereas .d.ts
are intended for type acquisition (IIRC jsdoc typings involve additional processing by the TypeScript language server). One of the main benefits of 11ty.ts
is that the exposed declaration supports plugin types automatically whenever a community plugin has exposed them, something which is great for plugins that require detailed options.
The pattern overall allows for things to be handled in isolation, alleviating potential headaches while keeping things separate and respecting the beautiful JS purity of the Eleventy source code. Appropriating it directly within the module, just as your above code snippet suggests can be done using a named export, as long as the declaration matches and is exposed within types
key of package.json.
In regards to https://github.com/11ty/eleventy/issues/3097#issuecomment-2256860341, I'm not sure I totally understand why are files be processed using the TypeScript compiler here, is this to generate .d.ts
from jsdoc annotations?
.eleventy.ts
processingThough a little unrelated to this issue specifically, but still in the realm of TypeScript, I am interested in the tactic for processing a .ts
configuration file (e.g, .eleventy.ts
). I have seen some discussions around this in the issues and IIRC the recommendation was to execute via ts-node. The inception of esbuild has given us a lot of opportunity to normalise logic, specifically CJS/ESM pain-points but also TypeScript. I am curious if there has been any consideration on supporting this by default?
Transforming .ts
eleventy configuration file into esm/cjs at runtime using esbuild would address the typical nuances developers encounter in more complex .eleventy
files. It might sound extraneous, but it's a relatively inexpensive operation to process config files using esbuild at execution runtime (excluding @11ty/eleventy
), with large files typically concluding in less than 100ms. Processing using esbuild here and then executing (i.e; build, watch etc) upon a temporary transformed .eleventy.js
would allow CJS, ESM and TypeScript files, including any additional modules (plugins) to be gracefully handled. This is somewhat the same tactic employed by other bundlers that support varying configuration file types.
On the topic of a TypeScript configuration file, I've personally used and seen widespread adoption of https://github.com/unjs/jiti. Seems like a good place to start as a loader for configuration files! Maybe best to create a separate issue for this topic? Not seeing any existing ones.
Haven't seen unjs. Very basic approach, excluding the analysis for determining whether executing in a CJS/ESM environment would be something like the below (untested and excluding varying gotchas) but general pattern would be:
import { build } from 'esbuild';
import path from 'node:path';
import { writeFileSync, unlink } from 'node:fs/promise'
const cwd = process.cwd();
async function extract (result) {
let run;
const { text } = result.outputFiles[0];
const outfile = options.filepath;
writeFileSync(outfile, text, 'utf8'); // write file
try {
// example sake, more logic required but the general gist
run = format === 'esm' ? import(outfile) : require(outfile);
} finally { await unlink(outfile); /* Remove temp outfile after executed*/ }
return run;
};
async function configRequire(format) {
const context = await build({
// config file name will need to be obtained, using .ts for example
entryPoints: [ path.join(cwd, '.eleventy.ts') ],
absWorkingDir: cwd,
outfile: 'out.js',
format, // CJS or ESM depending on ENV (pre-determine)
write: false,
platform: 'node',
sourcemap: 'inline',
bundle: true,
metafile: true,
plugins: [ /* additional plug would be needed for import.meta.url injects*/ ]
});
return extract(context); // the default export function is resolved
}
configRequire('cjs').then(fn => { /* fn() will hold the module.exports or default export */ })
Is your feature request related to a problem? Please describe.
TypeScript support, more specifically declarations within
.eleventy.js
configuration files seems to be a rather problematic for folks. The current approaches wherein using jsdoc annotations does not really suffice, nor does it solve plugin types. I've touched on this previously in issues, but I am yet to see any actionable steps in this area.Describe the solution you'd like
I've gone ahead and exposed support for Eleventy in an isolated manner via 11ty.ts and this brings type support for the available API, with both JSDoc descriptions and linked documentation references available in declarations. In addition, plugins which expose types are also supported using an auto-typed tactic.
I believe this will assist developers in their usage with 11ty and solves all issues pertaining to type related support. Given that auto-typed plugins is made available, this also allows for great support in th eco. The implementation is quite simple, developers can just consume and expose using a
defineConfig()
export.For Example:
Preview
https://github.com/11ty/eleventy/assets/7041324/569190b3-cd3a-4100-b4d4-fd7e0c910623
Describe alternatives you've considered
No response
Additional context
If the overall TypeScript discussions and issues around typings are not something planned or have been concluded upon, it would be nice that developers can more easily find this solution, from both a maintenance side and also availability side via the 11ty official documentation.
Lastly, the reason this is not made available to DefinitelyTyped is because their is JS required, given the
defineConfig
export. It is not possible to bridge fluid support without applying a wrapper.