From 24e768521fd7319de1822833e0a45f9e5d2313f3 Mon Sep 17 00:00:00 2001 From: Bastian Kruck Date: Thu, 15 Jan 2026 10:30:20 +0100 Subject: [PATCH 1/3] fix(ts-model-api): ensure to have only once instance of LanguageRegistry - to make sure we don't register the languages in one and wrap the nodes in another registry - the issue sometimes shows up when depending on model-client, ts-model-api and vue-model-api (sometimes causing multiple instances of the same js package) - avoids not finding concepts albeit them being registered --- ts-model-api/src/LanguageRegistry.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ts-model-api/src/LanguageRegistry.ts b/ts-model-api/src/LanguageRegistry.ts index addee3ee38..6d3cb6403a 100644 --- a/ts-model-api/src/LanguageRegistry.ts +++ b/ts-model-api/src/LanguageRegistry.ts @@ -4,8 +4,19 @@ import type {ITypedNode} from "./TypedNode.js"; import { TypedNode, UnknownTypedNode} from "./TypedNode.js"; import type {IConceptJS} from "./IConceptJS.js"; +const GLOBAL_INSTANCE_KEY = "__modelix_LanguageRegistry_INSTANCE__"; + export class LanguageRegistry { - public static INSTANCE: LanguageRegistry = new LanguageRegistry(); + public static readonly INSTANCE: LanguageRegistry = (() => { + const g = globalThis as unknown as Record; + let instance = g[GLOBAL_INSTANCE_KEY]; + if (!instance) { + instance = new LanguageRegistry(); + g[GLOBAL_INSTANCE_KEY] = instance; + } + return instance; + })(); + private languages: Map = new Map(); private nodeWrappers: Map TypedNode> | undefined = undefined private concepts: Map | undefined = undefined From a6f4abdeb30bd1060461f817ef1c59e26272db5a Mon Sep 17 00:00:00 2001 From: Bastian Kruck Date: Thu, 15 Jan 2026 10:36:21 +0100 Subject: [PATCH 2/3] chore(vue-model-api,ts-model-api): switch from CommonJS to modern ESNext - ESNext produces ES Modules (ESM) - eases bundling it in vite projects with moduleResolution: bundler - ESM allows treeshaking the assembled projects, reducing their file size --- ts-model-api/package.json | 1 + ts-model-api/src/index.ts | 19 +++++++++---------- ts-model-api/tsconfig.json | 2 +- vue-model-api/jest.config.js | 11 ++++++++++- vue-model-api/package.json | 1 + vue-model-api/tsconfig.json | 2 ++ 6 files changed, 24 insertions(+), 12 deletions(-) diff --git a/ts-model-api/package.json b/ts-model-api/package.json index 11b64e9779..6ffcdca4be 100644 --- a/ts-model-api/package.json +++ b/ts-model-api/package.json @@ -21,6 +21,7 @@ ], "type": "commonjs", "main": "dist/index", + "module": "dist/index.js", "typings": "dist/index.d.ts", "types": "dist/index.d.ts", "scripts": { diff --git a/ts-model-api/src/index.ts b/ts-model-api/src/index.ts index 8e269ec572..c62b0add50 100644 --- a/ts-model-api/src/index.ts +++ b/ts-model-api/src/index.ts @@ -1,10 +1,9 @@ - -export * from "./ChildrenAccessor.js" -export * from "./GeneratedConcept.js" -export * from "./GeneratedLanguage.js" -export * from "./IConceptJS.js" -export * from "./ILanguage.js" -export * from "./INodeJS.js" -export * from "./LanguageRegistry.js" -export * from "./TSModelClient.js" -export * from "./TypedNode.js" +export { ChildrenAccessor, ChildListAccessor, SingleChildAccessor } from "./ChildrenAccessor.js" +export { GeneratedConcept } from "./GeneratedConcept.js" +export { GeneratedLanguage } from "./GeneratedLanguage.js" +export { IConceptJS } from "./IConceptJS.js" +export { ILanguage } from "./ILanguage.js" +export { ChildRole, ReferenceRole, PropertyRole, toRoleJS, INodeJS } from "./INodeJS.js" +export { LanguageRegistry } from "./LanguageRegistry.js" +export { NodeId, IModelServerConnection, ModelService } from "./TSModelClient.js" +export { TypedNode, ITypedNode, UnknownTypedNode } from "./TypedNode.js" diff --git a/ts-model-api/tsconfig.json b/ts-model-api/tsconfig.json index a8bbad75be..7511be7a3a 100644 --- a/ts-model-api/tsconfig.json +++ b/ts-model-api/tsconfig.json @@ -28,7 +28,7 @@ "outDir": "dist", "declarationDir": "dist", "noUnusedLocals": false, - "module": "CommonJS", + "module": "ESNext", "resolveJsonModule": false, "target": "ES2020" }, diff --git a/vue-model-api/jest.config.js b/vue-model-api/jest.config.js index 3f12319470..2ab4ff78c3 100644 --- a/vue-model-api/jest.config.js +++ b/vue-model-api/jest.config.js @@ -1,6 +1,15 @@ /** @type {import('ts-jest').JestConfigWithTsJest} */ module.exports = { - preset: "ts-jest", + transform: { + "^.+\\.(t|j)sx?$": ["ts-jest", { tsconfig: { allowJs: true } }], + }, + moduleNameMapper: { + "^@modelix/ts-model-api$": "/../ts-model-api/src/index.ts", + "^@modelix/ts-model-api/(.*)\\.js$": "/../ts-model-api/src/$1", + "^@modelix/ts-model-api/(.*)$": "/../ts-model-api/src/$1", + "^(\\..*)\\.js$": "$1", + }, modulePathIgnorePatterns: ["/dist/"], testEnvironment: "node", + transformIgnorePatterns: ["node_modules/(?!(@modelix)/)"], }; diff --git a/vue-model-api/package.json b/vue-model-api/package.json index 6e5ee86945..f65e717c42 100644 --- a/vue-model-api/package.json +++ b/vue-model-api/package.json @@ -9,6 +9,7 @@ "directory": "vue-model-api" }, "main": "dist/index.js", + "module": "dist/index.js", "files": [ "dist/" ], diff --git a/vue-model-api/tsconfig.json b/vue-model-api/tsconfig.json index db83b45422..656c47a893 100644 --- a/vue-model-api/tsconfig.json +++ b/vue-model-api/tsconfig.json @@ -7,6 +7,8 @@ "rootDir": "src", "outDir": "dist", // 2021 is needed for FinalizationRegistry + "module": "ESNext", + "moduleResolution": "Node", "target": "es2021" } } From c4e965d0f3060e6165b40c40a04648094b5a9bb2 Mon Sep 17 00:00:00 2001 From: Bastian Kruck Date: Thu, 15 Jan 2026 10:37:19 +0100 Subject: [PATCH 3/3] chore: ignore bin folders --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6efaab0b80..c0718fd944 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .gradle/ +**/bin/ **/build /*/ignite/ .DS_Store