Hey Enonic-community,
I have just release new versions of our TypeScript libraries for XP: enonic-types@0.5.0 and and xp-codegen-plugin@2.0.0.
The good people at Enonic is currently working on “Typescript definitions in core”, but while we wait for that to be released, here are some new goodies in the mean time.
From Enonic Roadmap:
Highlights for xp-codegen-plugin release
Code is generated into a separate directory
The generated code will now be generated into its own directory ./.xp-codegen, and is of type *.d.ts. Then we don’t mix the developers code with the generated code anymore.
But if you do this trick in tsconfig.json
, you can overlap the file structures of ./src/main/resources with ./.xp-codegen, and reference the types with very similar paths as before.
{
"compilerOptions": {
...
+ "rootDirs": [
+ "./src/main/resources",
+ "./.xp-codegen"
+ ],
},
"include": [
+ "./.xp-codegen/**/*",
"./src/main/resources/**/*"
],
"exclude": ["./build/*"]
}
Generated types for content types can now be imported like this:
// The old way to import
-import type { Article } from "../../content-types/article/article";
-import type { Employee } from "../../content-types/employee/employee";
// The new way to import
+import type { Article, Employee } from "../../content-types";
// Or you can access globally defined type like this:
+type Article = XP.ContentTypes["com.mysite.app:article"];
Generate global declarations
There are also some new global
declarations that are automatically generated, which can be found at XP.ContentTypes
, XP.XData
and XP.SiteConfig
.
Highlights in the enonic-types npm package release
Use global declarations
Instead of being passed as type parameters, enonic-types will now use global declarations for XP.ContentTypes
, XP.XData
and XP.SiteConfig
.
This is more logical because XData
and SiteConfig
is per project, and not per content type. And this allows us to either specify them once, or generate the interfaces for them automatically.
They can be configured for a project like this:
import { MenuItem } from "../path-to-somewhere";
declare global {
namespace XP {
interface SiteConfig {
footer: string | string[] | undefined;
}
interface XData {
"com-mysite"?: {
"menu-item"?: MenuItem;
}
}
}
}
Content.type
is now a “string literal” passed in as type parameter
By having the Content .type
be a string literal that is passed in as a type parameter to Content
, we can now split a discrete union of content types by a simple if
-statement
on the type
field (just like we would do in JavaScript).
import { query } from "/lib/xp/content";
export function get(): XP.Response {
const res = query({
count: 100,
contentTypes: ["com.mysite:article", "com.mysite:employee"]
});
// the shape of res.hits is correctly inferred based on `contentTypes`
const contents: Array<Content<Article> | Content<Employee>> = res.hits;
contents.forEach((content) => {
// since we now know which shape of `data` belongs to which `type`, this is now possible
if (content.type === "com.mysite:article") {
// This would have failed earlier, since `content.type` as of type `string`
const article: Article = content.data;
log.info("Article: " + JSON.stringify(article))
} else {
// If it isn't an Article, it has to bee an Employee (based on `contentTypes` above)
const employee: Employee = content.data;
log.info("Employee: " + JSON.stringify(employee))
}
});
}
There will be a little work for users of xp-codegen-plugin to migrate to the new paths – sorry about that – but the result should be a bit cleaner code.
I hope you will like these new changes, there is some more info in the change logs:
- Release Generate all files in ./.xp-codegen directory · ItemConsulting/xp-codegen-plugin · GitHub
- Release Add global declarations for ContentTypes, XData and SiteConfig · ItemConsulting/enonic-types · GitHub
Have a great day!
– Tom Arild