Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
1f0d900
Add CSV model import: inference engine, backend endpoint, and unit tests
amirrza777 Jul 9, 2026
d6139d5
Remove edge label fix from CSV import branch (belongs in separate PR)
amirrza777 Jul 9, 2026
5a3a9e3
Add CSV import block syntax to model language and CSV-to-ModelData co…
amirrza777 Jul 10, 2026
4209220
Fix CSV import: use fileDataService to get metamodel data instead of …
amirrza777 Jul 10, 2026
1fe2d53
Fix CSV import: use fileDataService to get computed metamodel data
amirrza777 Jul 10, 2026
f3b7602
Fix compile error: handle JsonNull explicitly instead of elvis on non…
amirrza777 Jul 10, 2026
eb6cbbb
Write model file in DSL text format instead of JSON
amirrza777 Jul 10, 2026
927ec8b
Fix relative metamodel path in generated model DSL
amirrza777 Jul 10, 2026
30edfa9
Add language-csv and service-csv packages for CSV file support in wor…
amirrza777 Jul 11, 2026
7275d68
Fix service-csv Dockerfile and compose config to match existing servi…
amirrza777 Jul 11, 2026
bfced6b
Remove hardcoded port mapping for service-csv to avoid conflicts
amirrza777 Jul 11, 2026
77b5e20
Final CSV import: updated routes, inference engine, and tests
amirrza777 Jul 11, 2026
3ee7d4e
Add .DS_Store to gitignore
amirrza777 Jul 11, 2026
79647ea
Add ModelContributionPlugin system and language-model-csv contributio…
amirrza777 Jul 11, 2026
4afa5c9
Fix contribution plugin grammar merging and remove invalid TokenBuild…
amirrza777 Jul 11, 2026
e55bc44
Register CSV contribution plugin as built-in to model language at sta…
amirrza777 Jul 11, 2026
0afc194
Hardcode CSV contribution directly in modelPlugin to avoid ESM module…
amirrza777 Jul 11, 2026
9b836c2
Add import CSV syntax directly to model grammar as a first-class feature
amirrza777 Jul 11, 2026
42b8c79
Fix scope resolution for CsvClassImport class references
amirrza777 Jul 11, 2026
bf4f83f
Fix scope resolution for CsvClassImport: traverse two levels up to re…
amirrza777 Jul 11, 2026
75b673c
Register modelDataHandler in service-model for CSV import block support
amirrza777 Jul 11, 2026
e1a7804
Read CSV files in GModelFactory to render diagram nodes from import C…
amirrza777 Jul 12, 2026
5dd26cc
Fix modelGModelFactory: add CSV import block rendering with FileSyste…
amirrza777 Jul 12, 2026
4aa65d9
Add createCsvNodes to render diagram nodes directly from CSV import b…
amirrza777 Jul 12, 2026
286ac90
Remove synthetic PartialObjectInstance from extractElements, use crea…
amirrza777 Jul 12, 2026
5cbe9ff
Fix createCsvNodes: use proper GObjectNode builder with metadata and …
amirrza777 Jul 12, 2026
67feb39
Persist CSV node positions by carrying forward metadata from previous…
amirrza777 Jul 12, 2026
f4a6101
Remove CSV-to-model materialize endpoint and dead inference engine
amirrza777 Jul 14, 2026
640ba1f
Turn CSV import into a proper contribution plugin
amirrza777 Jul 14, 2026
9355be2
Add language-model-csv and service-model-csv to package-lock.json
amirrza777 Jul 14, 2026
1c775f7
Add explicit CSV column to property mapping
amirrza777 Jul 22, 2026
4653e59
Wait for service-csv health before starting workbench
amirrza777 Jul 22, 2026
eddadd6
Address Copilot review comments on CSV import PR
amirrza777 Jul 24, 2026
df6dc0a
Use curly braces with a keyword for explicit CSV column mapping
amirrza777 Jul 24, 2026
a380d1d
Show property values on CSV-imported diagram nodes
amirrza777 Aug 2, 2026
5750a85
Restore doc comments in modelTypes.ts and untrack .DS_Store files
amirrza777 Aug 2, 2026
db81b78
Delegate model data imports to contribution plugins
amirrza777 Aug 2, 2026
2da69eb
Merge remote-tracking branch 'upstream/main' into amir/csv-import
amirrza777 Aug 2, 2026
0e50d18
Merge amir/csv-import, moving explicit mapping into the plugin service
amirrza777 Aug 2, 2026
0653f50
Use plain nested braces for the CSV column mapping
amirrza777 Aug 2, 2026
342a9a9
Keep CSV instance names unique across imports of the same class
amirrza777 Aug 2, 2026
debf724
Merge branch 'amir/csv-import' into amir/csv-explicit-mapping
amirrza777 Aug 2, 2026
a724e37
Allow empty CSV files and scope metadata state to one validation call
amirrza777 Aug 4, 2026
19d131b
Merge branch 'amir/csv-import' into amir/csv-explicit-mapping
amirrza777 Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
copilot/
tools/
infra/.env
.DS_Store
97 changes: 97 additions & 0 deletions app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions app/packages/language-csv/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@mdeo/language-csv",
"version": "0.1.0",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": ["dist", "src"],
"dependencies": {
"@mdeo/language-common": "^0.1.0",
"@mdeo/language-shared": "^0.1.0"
},
"devDependencies": {
"@types/node": "^25.3.1",
"langium": "^4.2.1"
}
}
39 changes: 39 additions & 0 deletions app/packages/language-csv/src/csvPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
type LangiumLanguagePlugin,
type LangiumLanguagePluginProvider,
type LanguageServices,
type ExternalReferenceAdditionalServices
} from "@mdeo/language-common";
import {
DefaultAstSerializer,
SerializerFormatter,
registerDefaultTokenSerializers,
DefaultExternalReferenceCollector
} from "@mdeo/language-shared";
import type { ServerContributionPlugin } from "@mdeo/plugin";
import { CsvFileRule, CsvTerminals } from "./grammar/csvRules.js";

function createCsvPlugin(): LangiumLanguagePlugin<ExternalReferenceAdditionalServices> {
return {
rootRule: CsvFileRule,
additionalTerminals: CsvTerminals,
module: {
references: {
ExternalReferenceCollector: () => new DefaultExternalReferenceCollector()
},
lsp: {
Formatter: (services: LanguageServices & ExternalReferenceAdditionalServices) => new SerializerFormatter(services)
},
AstSerializer: (services: LanguageServices & ExternalReferenceAdditionalServices) => new DefaultAstSerializer(services)
},
postCreate(services: LanguageServices & ExternalReferenceAdditionalServices) {
registerDefaultTokenSerializers(services);
}
};
}

export const csvPluginProvider: LangiumLanguagePluginProvider<ExternalReferenceAdditionalServices> = {
create(_contributionPlugins: ServerContributionPlugin[], _languageJsUrl?: string): LangiumLanguagePlugin<ExternalReferenceAdditionalServices> {
return createCsvPlugin();
}
};
19 changes: 19 additions & 0 deletions app/packages/language-csv/src/grammar/csvRules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createTerminal, createRule, optional, WS } from "@mdeo/language-common";
import { CsvFile } from "./csvTypes.js";

/**
* Matches a whole CSV file as one token. The CSV language does no structural
* parsing of its own, the content is interpreted where it is imported.
*
* The pattern requires at least one character, since a terminal that can match
* the empty string would never advance the lexer. An empty file is handled by
* making the assignment optional in the rule below rather than by allowing an
* empty match here.
*/
export const ANY_TEXT = createTerminal("ANY_TEXT").as(/[\s\S]+/);

export const CsvFileRule = createRule("CsvFileRule")
.returns(CsvFile)
.as(({ set }) => [optional(set("content", ANY_TEXT))]);

export const CsvTerminals = [WS, ANY_TEXT];
15 changes: 15 additions & 0 deletions app/packages/language-csv/src/grammar/csvTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { createInterface, Optional, type ASTType } from "@mdeo/language-common";

/**
* A CSV file's contents, held as a single blob of text.
*
* `content` is optional because an empty file is a valid CSV file. The
* workbench offers a "Create New CSV" action, which produces an empty file, so
* requiring content would put every newly created CSV straight into a parse
* error state.
*/
export const CsvFile = createInterface("CsvFile").attrs({
content: Optional(String)
});

export type CsvFileType = ASTType<typeof CsvFile>;
3 changes: 3 additions & 0 deletions app/packages/language-csv/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./grammar/csvTypes.js";
export * from "./grammar/csvRules.js";
export * from "./csvPlugin.js";
13 changes: 13 additions & 0 deletions app/packages/language-csv/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist",
"composite": true
},
"include": ["src"],
"references": [
{ "path": "../language-common" },
{ "path": "../language-shared" }
]
}
18 changes: 18 additions & 0 deletions app/packages/language-model-csv/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@mdeo/language-model-csv",
"version": "0.1.0",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": ["dist", "src"],
"dependencies": {
"@mdeo/language-common": "^0.1.0",
"@mdeo/language-model": "^0.1.0",
"@mdeo/language-metamodel": "^0.1.0",
"@mdeo/language-shared": "^0.1.0"
},
"devDependencies": {
"@types/node": "^25.3.1",
"langium": "^4.2.1"
}
}
90 changes: 90 additions & 0 deletions app/packages/language-model-csv/src/csvPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {
type LangiumLanguagePlugin,
type LangiumLanguagePluginProvider,
type ExternalReferenceAdditionalServices,
GrammarDeserializationContext,
ID,
NEWLINE,
HIDDEN_NEWLINE,
INT,
FLOAT,
STRING
} from "@mdeo/language-common";
import {
DefaultAstSerializer,
IdValueConverter,
SerializerFormatter,
registerDefaultTokenSerializers,
NewlineAwareTokenBuilder,
addExternalReferenceCollectionPhase,
ActionHandlerRegistry,
type ActionHandlerRegistryAdditionalServices,
DefaultActionProvider
} from "@mdeo/language-shared";
import { generateModelContributionGrammar, ModelTerminals, ModelScopeProvider, ModelExternalReferenceCollector } from "@mdeo/language-model";
import { Class } from "@mdeo/language-metamodel";
import { createModelCsvContributionPlugin } from "./plugin/modelCsvContributionPlugin.js";

/**
* Combined services type for the standalone model-csv language.
* Reuses the base Model language's services, since the standalone grammar's
* root is a real `Model` node (an `import` line plus the CSV import block).
*/
export type ModelCsvServices = ExternalReferenceAdditionalServices & ActionHandlerRegistryAdditionalServices;

/**
* Deserialization context for the CSV grammar.
* Provides the external interface types and common terminals so the CSV
* grammar can be deserialized from its serialized form.
*/
const csvDeserializationContext = GrammarDeserializationContext.create([Class], [], [ID, NEWLINE, HIDDEN_NEWLINE, INT, FLOAT, STRING]);

/**
* The root rule for the standalone model-csv language.
* Generated from the CSV contribution plugin's grammar.
*/
const csvRootRule = generateModelContributionGrammar(createModelCsvContributionPlugin(), csvDeserializationContext);

/**
* The plugin for the standalone model-csv generated language.
* Its root type is a real `Model` node, so it reuses the base Model language's
* own scope provider and external reference collector directly.
*/
const modelCsvPlugin: LangiumLanguagePlugin<ModelCsvServices> = {
rootRule: csvRootRule,
additionalTerminals: ModelTerminals,
module: {
parser: {
TokenBuilder: () => new NewlineAwareTokenBuilder(new Set(["{"]), new Set(["("]), new Set(["}", ")"])),
ValueConverter: () => new IdValueConverter(),
ParserConfig: () => ({
maxLookahead: 4
})
},
references: {
ScopeProvider: (services) => new ModelScopeProvider(services),
ExternalReferenceCollector: () => new ModelExternalReferenceCollector()
},
lsp: {
Formatter: (services) => new SerializerFormatter(services)
},
AstSerializer: (services) => new DefaultAstSerializer(services),
action: {
ActionHandlerRegistry: () => new ActionHandlerRegistry(),
ActionProvider: () => new DefaultActionProvider()
}
},
postCreate(services) {
registerDefaultTokenSerializers(services);
addExternalReferenceCollectionPhase(services);
}
};

/**
* Provider for the standalone model-csv language plugin.
*/
export const modelCsvPluginProvider: LangiumLanguagePluginProvider<ModelCsvServices> = {
create(): LangiumLanguagePlugin<ModelCsvServices> {
return modelCsvPlugin;
}
};
Loading
Loading