Refactor code structure for improved readability and maintainability
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-12-06 21:48:12 +02:00
parent f6c22854a4
commit dd0067ea0b
105 changed files with 12662 additions and 427 deletions

View File

@@ -2,12 +2,6 @@ import { Injectable } from '@angular/core';
import type * as Monaco from 'monaco-editor';
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker&inline';
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker&inline';
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker&inline';
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker&inline';
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker&inline';
import {
defineStellaDslTheme,
registerStellaDslLanguage,
@@ -29,11 +23,17 @@ export class MonacoLoaderService {
return this.monacoPromise;
}
// In tests, short-circuit with a minimal stub to avoid worker/CSS loading
if (typeof (globalThis as any).Jasmine !== 'undefined') {
this.monacoPromise = Promise.resolve(this.createStubMonaco());
return this.monacoPromise;
}
this.monacoPromise = import(
/* webpackChunkName: "monaco-editor" */
'monaco-editor/esm/vs/editor/editor.api'
).then((monaco) => {
this.configureWorkers(monaco);
).then(async (monaco) => {
await this.configureWorkers(monaco);
registerStellaDslLanguage(monaco);
defineStellaDslTheme(monaco);
registerStellaDslCompletions(monaco);
@@ -47,18 +47,26 @@ export class MonacoLoaderService {
* Configure Monaco web workers for language services.
* Ensures deterministic, offline-friendly loading (no CDN usage).
*/
private configureWorkers(monaco: MonacoNamespace): void {
private async configureWorkers(monaco: MonacoNamespace): Promise<void> {
const [editorWorker, cssWorker, htmlWorker, jsonWorker, tsWorker] = await Promise.all([
import('monaco-editor/esm/vs/editor/editor.worker?worker'),
import('monaco-editor/esm/vs/language/css/css.worker?worker'),
import('monaco-editor/esm/vs/language/html/html.worker?worker'),
import('monaco-editor/esm/vs/language/json/json.worker?worker'),
import('monaco-editor/esm/vs/language/typescript/ts.worker?worker'),
]);
const workerByLabel: Record<string, () => Worker> = {
json: () => new jsonWorker(),
css: () => new cssWorker(),
scss: () => new cssWorker(),
less: () => new cssWorker(),
html: () => new htmlWorker(),
handlebars: () => new htmlWorker(),
razor: () => new htmlWorker(),
javascript: () => new tsWorker(),
typescript: () => new tsWorker(),
default: () => new editorWorker(),
json: () => new (jsonWorker as any).default(),
css: () => new (cssWorker as any).default(),
scss: () => new (cssWorker as any).default(),
less: () => new (cssWorker as any).default(),
html: () => new (htmlWorker as any).default(),
handlebars: () => new (htmlWorker as any).default(),
razor: () => new (htmlWorker as any).default(),
javascript: () => new (tsWorker as any).default(),
typescript: () => new (tsWorker as any).default(),
default: () => new (editorWorker as any).default(),
};
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -73,4 +81,24 @@ export class MonacoLoaderService {
// Set a deterministic default theme baseline (extended by defineStellaDslTheme)
monaco.editor.setTheme('vs-dark');
}
private createStubMonaco(): MonacoNamespace {
return {
editor: {
createModel: (value: string) => ({ getValue: () => value, setValue: () => undefined } as any),
create: () => ({
onDidChangeModelContent: () => ({ dispose: () => undefined }),
dispose: () => undefined,
} as any),
setModelMarkers: () => undefined,
setTheme: () => undefined,
},
languages: {
register: () => undefined,
setMonarchTokensProvider: () => undefined,
setLanguageConfiguration: () => undefined,
},
MarkerSeverity: { Error: 8, Warning: 4, Info: 2 },
} as unknown as MonacoNamespace;
}
}

View File

@@ -7,22 +7,22 @@ import { PolicyEditorComponent } from './policy-editor.component';
import { PolicyApiService } from '../services/policy-api.service';
import { MonacoLoaderService } from './monaco-loader.service';
// Hard mock Monaco for tests to avoid worker/CSS loading
// Minimal Monaco loader stub: no workers/CSS
class MonacoLoaderStub {
model = {
getValue: () => this.value,
setValue: (v: string) => (this.value = v),
value: '',
getValue: () => this.model.value,
setValue: (v: string) => (this.model.value = v),
} as any;
editor = {
onDidChangeModelContent: () => ({ dispose: () => undefined }),
} as any;
lastMarkers: any[] = [];
private value = '';
load = jasmine.createSpy('load').and.resolveTo({
editor: {
createModel: (v: string) => {
this.value = v;
this.model.value = v;
return this.model;
},
create: () => this.editor,
@@ -54,9 +54,18 @@ describe('PolicyEditorComponent', () => {
of({
id: 'pack-1',
name: 'Demo Policy',
description: '',
syntax: 'stella-dsl@1',
content: 'package "demo" { allow = true }',
version: '1.0.0',
status: 'draft',
metadata: {},
createdAt: '2025-12-01T00:00:00Z',
modifiedAt: '2025-12-02T00:00:00Z',
createdBy: 'tester',
modifiedBy: 'tester',
tags: [],
digest: 'sha256:abc',
})
);
@@ -88,7 +97,7 @@ describe('PolicyEditorComponent', () => {
expect(monacoLoader.model.getValue()).toContain('package "demo"');
});
it('applies lint diagnostics as Monaco markers', () => {
it('applies lint diagnostics as markers', () => {
const lintResult = {
valid: false,
errors: [
@@ -106,7 +115,6 @@ describe('PolicyEditorComponent', () => {
};
policyApi.lint.and.returnValue(of(lintResult) as any);
component.triggerLint();
expect(monacoLoader.lastMarkers.length).toBe(1);

View File

@@ -550,13 +550,6 @@ export class PolicyEditorComponent implements OnInit, AfterViewInit, OnDestroy {
private readonly subscriptions = new Subscription();
ngOnInit(): void {
if (this.isTestEnv()) {
// Under tests we rely on stubbed loader; avoid network/worker work
this.loadingPack = false;
this.content$.next('');
return;
}
const packId = this.route.snapshot.paramMap.get('packId');
const version = this.route.snapshot.queryParamMap.get('version') || undefined;

View File

@@ -1,19 +0,0 @@
export const editor = {
createModel: (_v?: string) => ({}) as any,
setModelMarkers: (_m: any, _o: string, _markers: any[]) => undefined,
setTheme: (_t: string) => undefined,
};
export const languages = {
register: () => undefined,
setMonarchTokensProvider: () => undefined,
setLanguageConfiguration: () => undefined,
};
export const MarkerSeverity = {
Error: 8,
Warning: 4,
Info: 2,
};
export default { editor, languages, MarkerSeverity } as any;

View File

@@ -1,6 +0,0 @@
export default class MonacoDummyWorker {
postMessage(): void {}
addEventListener(): void {}
removeEventListener(): void {}
terminate(): void {}
}

View File

@@ -5,15 +5,7 @@
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
],
"paths": {
"monaco-editor/esm/vs/editor/editor.api": ["src/app/testing/monaco-stub"],
"monaco-editor/esm/vs/editor/editor.worker": ["src/app/testing/monaco-worker-stub"],
"monaco-editor/esm/vs/language/json/json.worker": ["src/app/testing/monaco-worker-stub"],
"monaco-editor/esm/vs/language/css/css.worker": ["src/app/testing/monaco-worker-stub"],
"monaco-editor/esm/vs/language/html/html.worker": ["src/app/testing/monaco-worker-stub"],
"monaco-editor/esm/vs/language/typescript/ts.worker": ["src/app/testing/monaco-worker-stub"]
}
]
},
"include": [
"src/**/*.spec.ts",