@esfaenza/dpe-builder 20.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts ADDED
@@ -0,0 +1,2424 @@
1
+ import { Observable } from 'rxjs';
2
+ import { HttpClient } from '@angular/common/http';
3
+ import * as _angular_core from '@angular/core';
4
+ import { InjectionToken, EnvironmentProviders, Signal, AfterViewChecked } from '@angular/core';
5
+ import * as _esfaenza_dpe_builder from '@esfaenza/dpe-builder';
6
+ import { EFMarkerType, EFConnectableSide } from '@foblex/flow';
7
+
8
+ /**
9
+ * Modello della definizione DPE — traduzione **letterale** dei record C# di
10
+ * `docs/domain-model.md`.
11
+ *
12
+ * Questi tipi sono allineati **a mano** ai record di `Jace.DPE.Model` (ADR 0007: nessun
13
+ * generatore di tipi, nessuno JSON Schema). Sono due modelli in due linguaggi e il
14
+ * compilatore non dira' mai quando divergono: la fonte di verita' e' `docs/contracts.md` +
15
+ * `docs/domain-model.md`, e chi cambia un record C# aggiorna questo file nello stesso
16
+ * momento.
17
+ *
18
+ * Convenzioni, tutte conseguenza del contratto:
19
+ *
20
+ * - proprieta' in **camelCase**, perche' il JSON prodotto dal backend e' camelCase
21
+ * (`domain-model.md`, convenzioni generali);
22
+ * - gli enum C# diventano **unioni di stringhe letterali** con i nomi esatti dei valori: un
23
+ * `enum` TypeScript non e' assegnabile da una stringa arrivata dalla rete, e un valore
24
+ * numerico non e' cio' che il backend serializza;
25
+ * - le collezioni nel backend non sono mai nulle, ma il JSON le **omette quando vuote**
26
+ * (ADR 0003): qui sono opzionali e chi legge non presume che esistano;
27
+ * - `extensionData` esiste su **ogni** record (**I7**): sono proprieta' JSON non riconosciute,
28
+ * con valori **opachi**. L'editor le trasporta senza interpretarle.
29
+ *
30
+ * Nessuna regola di dominio vive qui: obbligatorieta' condizionali, unicita' dei nomi e
31
+ * compatibilita' dei tipi sono del backend. Le note `condiz.` nei commenti sono descrittive
32
+ * e servono a chi costruira' gli ispettori, non sono validazione.
33
+ */
34
+ /** Proprieta' JSON non riconosciute, conservate verbatim (**I7**). Valori opachi. */
35
+ type DpeExtensionData = Record<string, unknown>;
36
+ /** Base di ogni record del modello: `ExtensionData` sta su tutti, non solo sulla radice. */
37
+ interface DpeExtensible {
38
+ extensionData?: DpeExtensionData;
39
+ }
40
+ /** I sei tipi logici, nessun altro valore mai (ADR 0002). */
41
+ type LogicalType = 'String' | 'Number' | 'Integer' | 'DateTime' | 'Boolean' | 'Enum';
42
+ interface ColumnType extends DpeExtensible {
43
+ kind: LogicalType;
44
+ /** Condiz.: richiesto per `String` nei campi dichiarati. */
45
+ length?: number;
46
+ /** Solo `Number`. */
47
+ precision?: number;
48
+ /** Condiz.: richiesto per `Number` nei campi dichiarati. */
49
+ scale?: number;
50
+ /** Condiz.: non vuoto quando `kind === 'Enum'`. */
51
+ allowedValues?: string[];
52
+ }
53
+ type SortDirection = 'Ascending' | 'Descending';
54
+ interface OrderByField extends DpeExtensible {
55
+ /** Alias della colonna a monte. */
56
+ columnName: string;
57
+ /** Default `Ascending`. */
58
+ direction?: SortDirection;
59
+ }
60
+ type AggregateFunction = 'Count' | 'CountDistinct' | 'Sum' | 'Min' | 'Max' | 'Avg' | 'StdDev' | 'StdDevPop' | 'Variance' | 'VariancePop';
61
+ /** Base di tutti i nodi. `name` e' univoco nell'intera definizione (**I1**). */
62
+ interface DpeNode extends DpeExtensible {
63
+ name: string;
64
+ label: string;
65
+ description?: string;
66
+ }
67
+ /**
68
+ * I riferimenti a un nodo a monte sono dichiarati **opzionali** anche dove
69
+ * `domain-model.md` li marca obbligatori, e non e' un ammorbidimento del contratto: e' cio'
70
+ * che il contratto dice. In C# sono `string` con default `null`, l'obbligatorieta' e'
71
+ * verificata dalla validazione e "un modello incompleto e' un fatto normale (l'editor ne
72
+ * produce uno a ogni tasto)". Un nodo appena creato o appena scollegato **non ha** una
73
+ * sorgente: rappresentarla con la stringa vuota sarebbe un valore magico che il backend
74
+ * legge diversamente da un'assenza.
75
+ */
76
+ type SqlDialectKind = 'Sqlite' | 'SqlServer' | 'PostgreSql' | 'Oracle';
77
+ type DefinitionStatus = 'Active' | 'Inactive';
78
+ type DefinitionRunMode = 'Batch' | 'OnDemand';
79
+ interface DpeDefinition extends DpeExtensible {
80
+ /** Default `1`, sempre serializzato per primo. */
81
+ formatVersion: number;
82
+ name: string;
83
+ label: string;
84
+ description?: string;
85
+ /** Il dialetto e' **parte della definizione** (ADR 0009): cambiarlo e' una migrazione. */
86
+ dialect: SqlDialectKind;
87
+ /** Default `Inactive`. */
88
+ status?: DefinitionStatus;
89
+ /** Default `Batch`. */
90
+ runMode?: DefinitionRunMode;
91
+ /** Default `false`. */
92
+ isTemplate?: boolean;
93
+ parameters?: DpeParameter[];
94
+ /** Obbligatoria (>=1) in una definizione valida; assente in una in lavorazione. */
95
+ dataSources?: DataSourceNode[];
96
+ filters?: FilterNode[];
97
+ joins?: JoinNode[];
98
+ aggregates?: AggregateNode[];
99
+ transforms?: TransformNode[];
100
+ appends?: AppendNode[];
101
+ hierarchyPaths?: HierarchyPathNode[];
102
+ /** Modellati, non compilabili in v1 (`DPE_NODE_NOT_COMPILABLE`). */
103
+ forecasts?: ForecastNode[];
104
+ /** Modellati, non compilabili in v1. */
105
+ customNodes?: CustomNode[];
106
+ /** Obbligatoria (>=1) in una definizione valida. */
107
+ writebacks?: WritebackNode[];
108
+ atomicWritebacks?: AtomicWritebackNode[];
109
+ }
110
+ type ParameterRole = 'Value' | 'Filter' | 'Expression';
111
+ interface DpeParameter extends DpeExtensible {
112
+ name: string;
113
+ label: string;
114
+ description?: string;
115
+ role: ParameterRole;
116
+ /** Condiz.: richiesto quando `role === 'Value'`. */
117
+ valueType?: ColumnType;
118
+ /** Testo, interpretato secondo `valueType`, cultura invariante. */
119
+ defaultValue?: string;
120
+ /** Default `false`; ammesso solo per `role === 'Value'`. */
121
+ isMultiValue?: boolean;
122
+ }
123
+ type DataSourceKind = 'Table' | 'Csv' | 'ExternalDataset';
124
+ type CsvDelimiter = 'Comma' | 'Semicolon' | 'Tab' | 'Pipe' | 'Caret' | 'Backquote';
125
+ interface CsvSourceOptions extends DpeExtensible {
126
+ /** Default `Comma`. */
127
+ delimiter?: CsvDelimiter;
128
+ /** Default `true`. */
129
+ hasHeaderRow?: boolean;
130
+ /** Identificatore opaco risolto dall'host. */
131
+ location: string;
132
+ }
133
+ interface DataSourceField extends DpeExtensible {
134
+ /** Nome del campo nella tabella/file di origine. */
135
+ name: string;
136
+ /** Quando assente l'alias **e'** `name`: la normalizzazione e' del backend. */
137
+ alias?: string;
138
+ /** Condiz.: richiesto per `Csv`/`ExternalDataset`; per `Table` **ignorato**. */
139
+ declaredType?: ColumnType;
140
+ /** Default `false`. */
141
+ isPrimaryKey?: boolean;
142
+ }
143
+ interface DataSourceNode extends DpeNode {
144
+ kind: DataSourceKind;
145
+ /** Condiz.: richiesto per `kind === 'Table'`; nome noto al provider di metadati. */
146
+ tableName?: string;
147
+ /** Obbligatorio (>=1) in un nodo valido. */
148
+ fields?: DataSourceField[];
149
+ /** Condiz.: richiesto per `kind === 'Csv'`. */
150
+ csvOptions?: CsvSourceOptions;
151
+ /** Condiz.: richiesto per `kind === 'ExternalDataset'`. */
152
+ externalDatasetName?: string;
153
+ }
154
+ type FilterOperator = 'Equals' | 'NotEquals' | 'GreaterThan' | 'GreaterThanOrEqual' | 'LessThan' | 'LessThanOrEqual' | 'StartsWith' | 'EndsWith' | 'Contains' | 'DoesNotContain' | 'IsNull' | 'IsNotNull' | 'In' | 'NotIn';
155
+ interface FilterCriterion extends DpeExtensible {
156
+ /** >=1, univoco nel nodo, referenziato da `condition`. */
157
+ sequence: number;
158
+ /** Alias a monte. */
159
+ sourceFieldName: string;
160
+ operator: FilterOperator;
161
+ /** Condiz.: richiesto salvo `IsNull`/`IsNotNull` e salvo `inputVariable` presente. */
162
+ value?: string;
163
+ /** Nome di un `DpeParameter` con `role === 'Value'`; esclusivo con `value`. */
164
+ inputVariable?: string;
165
+ }
166
+ interface FilterNode extends DpeNode {
167
+ sourceName?: string;
168
+ /** Default `false`. */
169
+ isDynamic?: boolean;
170
+ /** Condiz.: richiesto (>=1) quando `isDynamic` e' falso. */
171
+ criteria?: FilterCriterion[];
172
+ /**
173
+ * Condiz.: richiesto quando `isDynamic` e' falso. Combinazione booleana dei `sequence`
174
+ * dei criteri (`1 AND (2 OR 3)`), **non** un'espressione SQL: e' l'unico linguaggio che il
175
+ * backend parsifica davvero.
176
+ */
177
+ condition?: string;
178
+ /** Condiz.: richiesto quando `isDynamic`; riferisce un parametro con `role === 'Filter'`. */
179
+ filterParameterName?: string;
180
+ }
181
+ type JoinKind = 'Inner' | 'LeftOuter' | 'RightOuter' | 'FullOuter' | 'Lookup';
182
+ interface JoinKey extends DpeExtensible {
183
+ primaryFieldName: string;
184
+ secondaryFieldName: string;
185
+ }
186
+ interface JoinResultField extends DpeExtensible {
187
+ /** Deve essere `primarySourceName` o `secondarySourceName` del nodo. */
188
+ sourceName: string;
189
+ sourceFieldName: string;
190
+ /** Univoco nel nodo (**I1**). */
191
+ alias: string;
192
+ }
193
+ interface JoinNode extends DpeNode {
194
+ primarySourceName?: string;
195
+ secondarySourceName?: string;
196
+ kind: JoinKind;
197
+ /** Obbligatorio (>=1) in un nodo valido. */
198
+ keys?: JoinKey[];
199
+ /** Lo schema di output e' **esplicito**: solo questi campi. */
200
+ fields?: JoinResultField[];
201
+ /** Default `false`; significativo solo per `kind === 'Lookup'`. */
202
+ allowsMultipleLookupValues?: boolean;
203
+ }
204
+ interface AggregateField extends DpeExtensible {
205
+ /** Alias a monte; assente **solo** per `Count` (conteggio righe). */
206
+ sourceFieldName?: string;
207
+ function: AggregateFunction;
208
+ alias: string;
209
+ }
210
+ interface AggregateNode extends DpeNode {
211
+ sourceName?: string;
212
+ /** Alias a monte; vuoto = aggregazione globale su una riga. */
213
+ groupBy?: string[];
214
+ /** Obbligatorio (>=1) in un nodo valido. */
215
+ fields?: AggregateField[];
216
+ }
217
+ type TransformKind = 'Expression' | 'Slice' | 'ComputeRelative';
218
+ interface ExpressionField extends DpeExtensible {
219
+ alias: string;
220
+ /** **SQL nativo del dialetto della definizione** (ADR 0006): passa verbatim. */
221
+ expression: string;
222
+ /** **Autorevole e non verificato** (ADR 0006). */
223
+ declaredType: ColumnType;
224
+ }
225
+ interface TransformNode extends DpeNode {
226
+ sourceName?: string;
227
+ kind: TransformKind;
228
+ /** Condiz.: richiesto (>=1) per `Expression`/`ComputeRelative`, vuoto per `Slice`. */
229
+ expressionFields?: ExpressionField[];
230
+ /** Condiz.: richiesto (>=1) per `Slice`, vuoto altrimenti. */
231
+ droppedFields?: string[];
232
+ /** Solo `ComputeRelative`. */
233
+ partitionBy?: string[];
234
+ /** Solo `ComputeRelative`. */
235
+ orderBy?: OrderByField[];
236
+ }
237
+ interface AppendNode extends DpeNode {
238
+ /** Obbligatorio (>=2) in un nodo valido. */
239
+ sources?: string[];
240
+ /** Default `false`. */
241
+ allowsDisjointSchema?: boolean;
242
+ }
243
+ interface HierarchyPathNode extends DpeNode {
244
+ sourceName?: string;
245
+ /** Chiave del nodo corrente. */
246
+ selfFieldName?: string;
247
+ /** Riferimento al padre. */
248
+ parentFieldName?: string;
249
+ /** Alias della colonna di percorso prodotta (`String`). */
250
+ pathFieldName?: string;
251
+ /** Default `true`. */
252
+ includesSelfValue?: boolean;
253
+ /** Condiz.: richiesto (>=1) quando `isAggregationRequired`. */
254
+ aggregateFields?: AggregateField[];
255
+ /** Default `false`. */
256
+ isAggregationRequired?: boolean;
257
+ rollupPercentageFieldName?: string;
258
+ }
259
+ type ForecastPeriodType = 'Year' | 'YearQuarter' | 'YearMonth' | 'YearWeek' | 'YearMonthDay' | 'FiscalYear' | 'FiscalYearQuarter' | 'FiscalYearMonth' | 'FiscalYearWeek';
260
+ type ForecastModelType = 'Auto' | 'Additive' | 'Multiplicative';
261
+ type ForecastAccuracy = 'None' | 'Eighty' | 'NinetyFive';
262
+ type DatePart = 'Second' | 'Minute' | 'Hour' | 'Day' | 'Week' | 'Month' | 'Quarter' | 'Year';
263
+ interface ForecastAggregationField extends DpeExtensible {
264
+ fieldName: string;
265
+ function: AggregateFunction;
266
+ resultAlias: string;
267
+ }
268
+ interface ForecastGroupField extends DpeExtensible {
269
+ fieldName: string;
270
+ /** Condiz.: richiesto quando il campo e' `DateTime`. */
271
+ datePart?: DatePart;
272
+ }
273
+ /** Modellato per intero, **non compilabile in v1** (`DPE_NODE_NOT_COMPILABLE`). */
274
+ interface ForecastNode extends DpeNode {
275
+ sourceName?: string;
276
+ dateFieldName?: string;
277
+ periodType?: ForecastPeriodType;
278
+ /** Default `1`, ammesso 1..100. */
279
+ periodCount?: number;
280
+ /** Alias della colonna di inizio periodo prodotta. */
281
+ periodStartFieldName?: string;
282
+ /** Default `Auto`. */
283
+ modelType?: ForecastModelType;
284
+ /** `null`/assente = automatica; ammesso 2..24. */
285
+ seasonality?: number;
286
+ /** Default `None`. */
287
+ accuracyPercent?: ForecastAccuracy;
288
+ /** Default `false`. */
289
+ excludesLastPeriod?: boolean;
290
+ /** Obbligatorio (>=1) in un nodo valido. */
291
+ aggregationFields?: ForecastAggregationField[];
292
+ groupFields?: ForecastGroupField[];
293
+ }
294
+ /** Usato dove uno schema si **dichiara** invece di derivarlo. */
295
+ interface DeclaredField extends DpeExtensible {
296
+ name: string;
297
+ type: ColumnType;
298
+ }
299
+ interface CustomNodeParameter extends DpeExtensible {
300
+ name: string;
301
+ value: string;
302
+ }
303
+ /** Modellato per intero, **non compilabile in v1**. */
304
+ interface CustomNode extends DpeNode {
305
+ /** Obbligatorio (>=1) in un nodo valido. */
306
+ sources?: string[];
307
+ extensionName: string;
308
+ extensionNamespace?: string;
309
+ parameters?: CustomNodeParameter[];
310
+ /**
311
+ * Obbligatorio (>=1): senza schema dichiarato la propagazione (**I4**) si interrompe e
312
+ * tutto cio' che sta a valle diventa invalidabile.
313
+ */
314
+ outputFields?: DeclaredField[];
315
+ }
316
+ type WritebackTargetKind = 'Database' | 'Json' | 'Csv';
317
+ type WritebackOperation = 'Insert' | 'Update' | 'Upsert' | 'Delete';
318
+ type WritebackFieldRole = 'Value' | 'PrimaryKey' | 'QualifierKey';
319
+ interface WritebackFieldMapping extends DpeExtensible {
320
+ /** Condiz.: alias a monte; assente quando `runtimeParameterName` e' presente. */
321
+ sourceFieldName?: string;
322
+ targetFieldName: string;
323
+ /** Il valore viene da un parametro, non dalla riga; esclusivo con `sourceFieldName`. */
324
+ runtimeParameterName?: string;
325
+ /** Default `Value`. */
326
+ role?: WritebackFieldRole;
327
+ relationshipName?: string;
328
+ /** Condiz.: richiesto quando `relationshipName` e' presente. */
329
+ parentName?: string;
330
+ /** Default `false`; se `true`, `sourceFieldName` non e' richiesto. */
331
+ isAutoGenerated?: boolean;
332
+ }
333
+ /**
334
+ * Opzioni dell'artefatto JSON (`contracts.md` §2, «Opzioni degli artefatti»). Sono **solo**
335
+ * scelte di formato, mai di destinazione (ADR 0010).
336
+ */
337
+ interface JsonArtifactOptions extends DpeExtensible {
338
+ /** Default `false`: JSON compatto, array di oggetti. */
339
+ indented?: boolean;
340
+ }
341
+ /**
342
+ * Opzioni dell'artefatto CSV. Il quoting **non e' configurabile** di proposito: si quota
343
+ * quando serve e si raddoppiano le virgolette, perche' un quoting opzionale produce file che
344
+ * qualcuno non riesce a rileggere.
345
+ */
346
+ interface CsvArtifactOptions extends DpeExtensible {
347
+ /** Default `Comma`. */
348
+ delimiter?: CsvDelimiter;
349
+ /** Default `true`. */
350
+ includesHeaderRow?: boolean;
351
+ }
352
+ interface WritebackNode extends DpeNode {
353
+ sourceName?: string;
354
+ /** **Determina l'artefatto prodotto**. */
355
+ target: WritebackTargetKind;
356
+ /** >=1, univoco fra tutti i writeback e gli atomic writeback. */
357
+ sequence: number;
358
+ /** Condiz.: richiesto per `target === 'Database'`. */
359
+ tableName?: string;
360
+ /** Condiz.: richiesto per `target === 'Database'`; assente per `Json`/`Csv`. */
361
+ operation?: WritebackOperation;
362
+ /** Obbligatorio (>=1) in un nodo valido. */
363
+ fields?: WritebackFieldMapping[];
364
+ /** Espressione SQL nativa applicata al risultato (ADR 0006). */
365
+ filterCondition?: string;
366
+ /** Condiz.: richiesto per `operation === 'Upsert'`. */
367
+ externalIdFieldName?: string;
368
+ /** Default `false`. */
369
+ onlyChangedRows?: boolean;
370
+ /** Solo `target === 'Json'`. */
371
+ jsonOptions?: JsonArtifactOptions;
372
+ /** Solo `target === 'Csv'`. */
373
+ csvOptions?: CsvArtifactOptions;
374
+ }
375
+ interface AtomicWritebackRelationship extends DpeExtensible {
376
+ /** Nome di un `WritebackNode` con `target === 'Database'`. */
377
+ parentWritebackName?: string;
378
+ parentFieldName?: string;
379
+ childWritebackName?: string;
380
+ childFieldName?: string;
381
+ relationshipName?: string;
382
+ /** Ordine dentro il gruppo atomico. */
383
+ sequence: number;
384
+ }
385
+ interface AtomicWritebackNode extends DpeNode {
386
+ /** Nello stesso spazio di numerazione dei `WritebackNode`. */
387
+ sequence: number;
388
+ /** Obbligatorio (>=1) in un nodo valido. */
389
+ relationships?: AtomicWritebackRelationship[];
390
+ }
391
+ /**
392
+ * Le collezioni di nodi della radice, con il tipo che ciascuna contiene.
393
+ *
394
+ * Esiste perche' ogni utility che cammina il documento (derivazione degli archi, rinomina,
395
+ * catalogo della palette) deve nominare le collezioni **una volta sola**: una collezione
396
+ * dimenticata in uno dei tre posti non produce nessun errore, produce un arco che non
397
+ * compare o un riferimento che resta rotto dopo una rinomina.
398
+ */
399
+ interface DpeNodeCollectionMap {
400
+ dataSources: DataSourceNode;
401
+ filters: FilterNode;
402
+ joins: JoinNode;
403
+ aggregates: AggregateNode;
404
+ transforms: TransformNode;
405
+ appends: AppendNode;
406
+ hierarchyPaths: HierarchyPathNode;
407
+ forecasts: ForecastNode;
408
+ customNodes: CustomNode;
409
+ writebacks: WritebackNode;
410
+ atomicWritebacks: AtomicWritebackNode;
411
+ }
412
+ type DpeNodeCollectionName = keyof DpeNodeCollectionMap;
413
+ /** Qualunque nodo della definizione. */
414
+ type DpeAnyNode = DpeNodeCollectionMap[DpeNodeCollectionName];
415
+ /**
416
+ * L'elenco dei nomi di collezione in forma di valore, nell'ordine in cui i nodi si leggono
417
+ * (sorgenti -> trasformazioni -> sink). `keyof` non produce un array a runtime: questo
418
+ * elenco e' l'unico posto in cui vive l'ordine.
419
+ */
420
+ declare const DPE_NODE_COLLECTIONS: readonly DpeNodeCollectionName[];
421
+
422
+ /**
423
+ * Diagnostiche — traduzione letterale di `Jace.DPE.Diagnostics` (`docs/contracts.md` §1).
424
+ *
425
+ * Tipi allineati **a mano** ai record C# (ADR 0007). L'editor **consuma** queste
426
+ * diagnostiche e non ne produce: nessuna regola di dominio vive nel frontend, quindi in
427
+ * questo file non ci sono ne' codici inventati ne' messaggi ricomposti. Il `message` arriva
428
+ * dal backend, che e' l'unico posto in cui un messaggio viene composto.
429
+ */
430
+ type DiagnosticSeverity = 'Info' | 'Warning' | 'Error';
431
+ interface DiagnosticPathSegment {
432
+ /** `"filters"`, `"criteria"`, `"fields"`, ... */
433
+ collection?: string;
434
+ /** Nome del nodo/alias, se applicabile. */
435
+ name?: string;
436
+ /** Indice nella collezione, se applicabile. */
437
+ index?: number;
438
+ }
439
+ /**
440
+ * Percorso strutturato del rilievo.
441
+ *
442
+ * **Due forme, entrambe da gestire** (`contracts.md` §1, limite dichiarato): in
443
+ * deserializzazione i nomi dei nodi non sono ancora noti e i segmenti portano solo l'indice
444
+ * (`filters[0].sourceName`); dalla validazione portano il nome (`filters/OnlyActive`). Chi
445
+ * naviga fino al campo deve accettare tutt'e due, altrimenti le diagnostiche del caricamento
446
+ * di un file non sono cliccabili.
447
+ */
448
+ interface DiagnosticPath {
449
+ segments?: DiagnosticPathSegment[];
450
+ /** Nome della proprieta' in causa, camelCase. */
451
+ field?: string;
452
+ }
453
+ /**
454
+ * `arguments` e' un dizionario di stringhe con **chiavi canoniche** (`contracts.md` §1):
455
+ * `node`, `field`, `column`, `alias`, `name`, `table`, `parameter`, `dialect`, `construct`,
456
+ * `expected`, `actual`, `value`, `sequence`, `condition`, `token`, `truncated`. L'editor le
457
+ * legge per costruire etichette, non per riscrivere il messaggio.
458
+ */
459
+ interface Diagnostic {
460
+ /** `DiagnosticCodes.*` del backend. Il frontend non ne dichiara l'elenco: e' del backend. */
461
+ code: string;
462
+ severity: DiagnosticSeverity;
463
+ path?: DiagnosticPath;
464
+ arguments?: Record<string, string>;
465
+ /** Derivato da `code` + `arguments`, cultura invariante. */
466
+ message: string;
467
+ }
468
+ /**
469
+ * L'unico codice che significa "hai fatto bene, siamo noi": nodo valido ma non ancora
470
+ * compilabile (`Forecast`, `CustomNode`, costrutto non supportato — **I10**). Va distinto
471
+ * visivamente dai `DPE_MODEL_*`, che invece l'utente deve correggere.
472
+ *
473
+ * E' l'unica costante di codice diagnostico che la libreria dichiara, e non e' una
474
+ * duplicazione del dominio: e' la sola distinzione che cambia **come si rende** un rilievo.
475
+ */
476
+ declare const DPE_NODE_NOT_COMPILABLE = "DPE_NODE_NOT_COMPILABLE";
477
+ /** Rappresentazione testuale del percorso, nella forma usata dai messaggi del backend. */
478
+ declare function diagnosticPathToString(path: DiagnosticPath | undefined): string;
479
+
480
+ /**
481
+ * Tipi di richiesta/risposta del service DPE — traduzione letterale di `docs/contracts.md`
482
+ * §2 (provider di metadati), §3 (SQL emesso) e §5 (il service).
483
+ *
484
+ * Allineati **a mano** ai record C# (ADR 0007). Cio' che non e' trasportabile non c'e':
485
+ * `DpeContext` porta i provider dell'host (`ITableMetadataProvider`, `IDataQueryProvider`,
486
+ * `IArtifactSink`, `ILogger`, `IClock`) e vive **dentro** il backend, quindi non ha un
487
+ * corrispettivo TypeScript. Lo stesso vale per `Execute`: l'editor non esegue, non
488
+ * materializza artefatti e non ha bisogno di `DpeExecuteResult`.
489
+ */
490
+
491
+ /**
492
+ * Cio' che l'ambiente ospite **dichiara** all'editor. Non e' un tipo del backend C#: `IDpeService`
493
+ * non cambia (ADR 0017), e l'host lo compone con cio' che gia' sa della propria installazione.
494
+ *
495
+ * Nasce con un solo campo e si estende **per aggiunta**: e' il posto previsto per i fatti
496
+ * dell'ambiente, non un contenitore da riempire in anticipo.
497
+ */
498
+ interface DpeEnvironment {
499
+ /** Il dialetto del database di destinazione. Dichiarato, mai scelto dall'utente dell'editor. */
500
+ readonly dialect: SqlDialectKind;
501
+ }
502
+ /**
503
+ * Riga di catalogo: identita' e fatti che l'ospite conosce **senza** caricare la definizione.
504
+ *
505
+ * Distinto da `DpeDefinition` per costruzione, e non per comodita': elencare non deve costare N
506
+ * caricamenti completi. Non ha un corrispettivo in `IDpeService` e non deve averlo — il service
507
+ * valida, compila ed esegue; dove le definizioni vivano e' dell'ospite (ADR 0007), che non ha
508
+ * ne' orologio ne' archiviazione lato libreria.
509
+ *
510
+ * I quattro campi in coda sono facoltativi in senso pieno: assenti, la riga **non li mostra e
511
+ * non li stima**. Contare i nodi lato client vorrebbe dire caricare tutte le definizioni per
512
+ * disegnare un elenco, e dedurre `updatedAt` e' impossibile.
513
+ */
514
+ interface DpeDefinitionSummary {
515
+ /** La chiave. Non esiste un id distinto dal nome (ADR 0019): rinominare e' cambiare chiave. */
516
+ name: string;
517
+ label: string;
518
+ description?: string;
519
+ dialect: SqlDialectKind;
520
+ status?: DefinitionStatus;
521
+ runMode?: DefinitionRunMode;
522
+ isTemplate?: boolean;
523
+ /** ISO 8601. Lo scrive l'ospite: la libreria non ha orologio. Assente = non mostrato. */
524
+ updatedAt?: string;
525
+ updatedBy?: string;
526
+ /** Numero di nodi. Lo conta l'ospite, **mai** il client. Assente = non mostrato. */
527
+ nodeCount?: number;
528
+ /**
529
+ * Esito dell'ultima validazione **noto all'ospite**: riportato, non ricalcolato. Puo' essere
530
+ * vecchio, quindi la riga lo mostra come stato noto e non come verita' — il frontend non
531
+ * valida nulla, e dedurlo qui sarebbe una validazione fatta dal client per interposta persona.
532
+ */
533
+ hasErrors?: boolean;
534
+ }
535
+ /**
536
+ * Tre esiti, **non due** (ADR 0004): "dichiarata", "dichiarata senza campi" e
537
+ * "sconosciuta" sono situazioni diverse e l'editor le mostra diverse. Chi implementa
538
+ * l'interfaccia non appiattisce `Unknown` in una lista di campi vuota.
539
+ */
540
+ type TableLookupOutcome = 'Declared' | 'DeclaredWithoutFields' | 'Unknown';
541
+ interface TableSummary {
542
+ name: string;
543
+ description?: string;
544
+ }
545
+ interface FieldRelationship {
546
+ targetTableName: string;
547
+ targetFieldName: string;
548
+ }
549
+ interface FieldDescriptor {
550
+ name: string;
551
+ description?: string;
552
+ type: ColumnType;
553
+ isKey: boolean;
554
+ isNullable: boolean;
555
+ /** Assente quando il campo non e' una relazione. */
556
+ relationship?: FieldRelationship;
557
+ }
558
+ interface TableDescriptor {
559
+ name: string;
560
+ description?: string;
561
+ fields?: FieldDescriptor[];
562
+ }
563
+ interface TableLookupResult {
564
+ outcome: TableLookupOutcome;
565
+ /** Presente solo con `outcome === 'Declared'`. */
566
+ table?: TableDescriptor;
567
+ }
568
+ interface SqlParameterValue {
569
+ /** Senza prefisso di dialetto: `"p0"`, `"param_StartDate"`. */
570
+ name: string;
571
+ type: LogicalType;
572
+ /** `null` ammesso. Valore opaco per l'editor, che lo mostra e non lo interpreta. */
573
+ value: unknown;
574
+ }
575
+ interface SqlStatement {
576
+ /** Porta i marcatori nella forma del dialetto (`@p0`, `:p0`, `$1`). */
577
+ text: string;
578
+ parameters?: SqlParameterValue[];
579
+ }
580
+ interface DpeColumnInfo {
581
+ name: string;
582
+ type: ColumnType;
583
+ /**
584
+ * Informativa (**I4**): serve alla vista dello schema, non blocca la compilazione. Il
585
+ * frontend non la calcola — arriva da qui.
586
+ */
587
+ isNullable: boolean;
588
+ }
589
+ interface DpeNodeSchemaInfo {
590
+ nodeName: string;
591
+ columns?: DpeColumnInfo[];
592
+ /**
593
+ * `false` = nodo **valido ma non compilabile** (**I10**): e' un limite nostro, non un
594
+ * errore dell'utente, e va reso diverso da un nodo invalido.
595
+ */
596
+ isCompilable: boolean;
597
+ }
598
+ interface DpeWritebackStep {
599
+ writebackName: string;
600
+ sequence: number;
601
+ target: WritebackTargetKind;
602
+ /** Assente per i target `Json`/`Csv`. */
603
+ operation?: WritebackOperation;
604
+ tableName?: string;
605
+ /**
606
+ * Campo di corrispondenza dell'`Upsert`; assente per ogni altra operazione. E' un
607
+ * `targetFieldName`: si ritrova in `targetMapping` per risalire alla colonna del result set
608
+ * (ADR 0016).
609
+ */
610
+ externalIdFieldName?: string;
611
+ /** Presente se il writeback appartiene a un gruppo atomico. */
612
+ atomicGroupName?: string;
613
+ /**
614
+ * Dichiarato, **non implementato dalla libreria**: il change tracking e' dell'host
615
+ * (ADR 0011) e non influenza l'SQL generato. Va mostrato come una dichiarazione che l'host
616
+ * deve onorare, non come una cosa che il motore fa.
617
+ */
618
+ onlyChangedRows?: boolean;
619
+ }
620
+ interface DpeValidateResult {
621
+ hasErrors: boolean;
622
+ /** Esaustive (**I6**): l'elenco completo, non il primo rilievo. */
623
+ diagnostics?: Diagnostic[];
624
+ /** Ordine topologico. */
625
+ schemas?: DpeNodeSchemaInfo[];
626
+ executionOrder?: string[];
627
+ writebackSequence?: DpeWritebackStep[];
628
+ }
629
+ /**
630
+ * Valore di un parametro di runtime per una compilazione (`DpeParameterValue`).
631
+ *
632
+ * `value` e' **opaco**: il tipo dichiarato del parametro lo conosce il backend, che lo
633
+ * interpreta secondo `ColumnType` in cultura invariante. L'editor lo trasporta e lo mostra,
634
+ * non lo converte.
635
+ */
636
+ interface DpeParameterValue {
637
+ name: string;
638
+ value: unknown;
639
+ }
640
+ /**
641
+ * Cio' che serve all'host per **eseguire** la scrittura che la libreria non esegue
642
+ * (`contracts.md` §2, «`DpeFieldMappingInfo`»): senza, l'host riceve un result set e non sa
643
+ * quale colonna va in quale campo ne' quale sia la chiave.
644
+ */
645
+ interface DpeFieldMappingInfo {
646
+ /** Nome della colonna nel result set dello `SqlStatement`. */
647
+ resultColumnName?: string;
648
+ targetFieldName: string;
649
+ role: WritebackFieldRole;
650
+ /** Presente: il valore viene da un parametro, non dalla riga. */
651
+ runtimeParameterName?: string;
652
+ /** La destinazione genera il valore: non e' nel result set. */
653
+ isAutoGenerated?: boolean;
654
+ relationshipName?: string;
655
+ parentName?: string;
656
+ }
657
+ interface DpeCompiledWriteback {
658
+ writebackName: string;
659
+ sequence: number;
660
+ statement: SqlStatement;
661
+ resultColumns?: DpeColumnInfo[];
662
+ /** Vedi {@link DpeFieldMappingInfo}: forma provvisoria. */
663
+ targetMapping?: DpeFieldMappingInfo[];
664
+ }
665
+ interface DpeCompileResult {
666
+ hasErrors: boolean;
667
+ diagnostics?: Diagnostic[];
668
+ databaseWritebacks?: DpeCompiledWriteback[];
669
+ /** SQL di lettura, non ancora eseguito. */
670
+ fileWritebacks?: DpeCompiledWriteback[];
671
+ writebackSequence?: DpeWritebackStep[];
672
+ }
673
+
674
+ /**
675
+ * Quali primitive **opzionali** l'ospite implementa davvero — `contracts.md` §7, normativo.
676
+ *
677
+ * La rilevazione e' per **identita' del metodo**: se il metodo dell'istanza e' ancora quello del
678
+ * prototipo di `DpeBuilderApi`, l'ospite non lo ha sovrascritto e la primitiva non c'e'. E'
679
+ * esatta, non richiede una primitiva di interrogazione e non aggiunge un giro di rete.
680
+ *
681
+ * Perche' un solo posto: la disponibilita' va saputa **prima del clic**. Lo schema precedente —
682
+ * partire da «disponibile» e scoprire l'assenza dal primo `MissingService` — mostra un comando
683
+ * attivo che fallisce alla pressione, cioe' insegna a non fidarsi dei bottoni, e per giunta
684
+ * costringe ogni consumatore a ripetere lo stesso trattamento dell'errore.
685
+ *
686
+ * Regola per chi implementa un host (normativa, `contracts.md` §7): **chi non supporta una
687
+ * primitiva non la sovrascrive**. Una sovrascrittura che lancia subito non equivale all'assenza —
688
+ * l'editor la considera disponibile e mostra il comando attivo.
689
+ *
690
+ * **Dichiarazione sottrattiva (ADR 0020).** Da quando la libreria spedisce un client HTTP che
691
+ * implementa tutte e dieci le primitive, l'identita' da sola non basta: chi eredita quel client
692
+ * non puo' dis-sovrascrivere un metodo. Disponibile diventa quindi «**sovrascritta** e **non
693
+ * elencata** in `unsupportedPrimitives`». La seconda meta' e' solo sottrattiva — non rende
694
+ * disponibile cio' che non e' implementato — e resta calcolata in questo file e in nessun altro.
695
+ */
696
+
697
+ /** Le primitive che un ambiente ospite puo' legittimamente non offrire. */
698
+ type DpeOptionalPrimitive = 'compilePreview' | 'load' | 'save' | 'getEnvironment' | 'listDefinitions' | 'createDefinition' | 'deleteDefinition';
699
+ declare function dpeIsPrimitiveAvailable(api: DpeBuilderApi, primitive: DpeOptionalPrimitive): boolean;
700
+ /** L'insieme delle primitive disponibili: comodo per fotografarlo una volta alla costruzione. */
701
+ interface DpeCapabilities {
702
+ readonly compilePreview: boolean;
703
+ readonly load: boolean;
704
+ readonly save: boolean;
705
+ readonly getEnvironment: boolean;
706
+ readonly listDefinitions: boolean;
707
+ readonly createDefinition: boolean;
708
+ readonly deleteDefinition: boolean;
709
+ }
710
+ declare function dpeReadCapabilities(api: DpeBuilderApi): DpeCapabilities;
711
+ /**
712
+ * Disponibilita' di un comando, con **il motivo** quando manca: un bottone disabilitato che non
713
+ * dice perche' manda a cercare un guasto che non c'e'.
714
+ */
715
+ interface DpeCommandAvailability {
716
+ readonly isAvailable: boolean;
717
+ /** Presente **solo** quando il comando non e' disponibile. Va nel `title` del bottone. */
718
+ readonly reason?: string;
719
+ }
720
+ /**
721
+ * Il comando di **creazione** e' l'unico che dipende da **due** primitive
722
+ * (`contracts.md` §7, normativo): `createDefinition` per scrivere, e `getEnvironment` perche' il
723
+ * dialetto della definizione nuova viene dall'ambiente (ADR 0017).
724
+ *
725
+ * Perche' senza `getEnvironment` si disabilita invece di ripiegare su un dialetto qualsiasi: una
726
+ * definizione creata per il dialetto sbagliato porta espressioni SQL native (ADR 0006) da
727
+ * riscrivere tutte, e chiederlo all'utente e' proprio la scelta che l'ADR 0017 ha tolto. Un
728
+ * comando disabilitato che dice perche' e' meglio di entrambe; il rimedio per l'ospite e' una
729
+ * riga, implementare `getEnvironment`.
730
+ *
731
+ * Sta qui e non dentro un componente per la stessa ragione delle altre: la disponibilita' si sa
732
+ * **prima del clic**, e in un solo posto.
733
+ */
734
+ declare function dpeCreateCommandAvailability(capabilities: DpeCapabilities): DpeCommandAvailability;
735
+
736
+ /**
737
+ * L'unica porta verso il backend — `docs/contracts.md` §7.
738
+ *
739
+ * **Non esiste un documento di endpoint: il contratto e' questa classe astratta** (ADR 0007).
740
+ * Fa anche da token di dependency injection: chi integra l'editor fornisce una
741
+ * implementazione e la registra come provider di `DpeBuilderApi`.
742
+ *
743
+ * Due conseguenze da non aggirare:
744
+ *
745
+ * 1. **questo file non conosce HTTP.** Nessun `HttpClient`, nessun `fetch`, nessun URL qui ne'
746
+ * in nessuno store o componente. L'ADR 0020 ha spostato il client HTTP **dentro** la libreria
747
+ * (`lib/api/http-dpe-builder-api.ts`), quindi la regola non e' piu' «zero HTTP in
748
+ * `projects/dpe-builder`» ma «zero HTTP fuori da quel file»: e' *una* implementazione fra le
749
+ * possibili, non la definizione del contratto, che resta questa classe;
750
+ * 2. **un dato nuovo dal backend e' un metodo nuovo qui**, mai una chiamata dentro un
751
+ * componente.
752
+ *
753
+ * I metodi con implementazione di default rifiutano con `DpeApiError('MissingService', ...)`:
754
+ * un ambiente che non li espone lascia l'editor funzionante con il singolo comando
755
+ * disabilitato. Un'anteprima SQL non disponibile disabilita l'anteprima, non l'editor.
756
+ *
757
+ * I metodi restituiscono `Observable` perche' l'I/O del frontend e' asincrono per natura. Il
758
+ * vincolo di sincronia della libreria C# riguarda il backend: qui si traduce solo nel fatto
759
+ * che una chiamata occupa il chiamante finche' non termina, quindi chi la invoca mostra
760
+ * l'attesa e non incatena una validazione a ogni battitura senza debounce.
761
+ */
762
+
763
+ declare abstract class DpeBuilderApi {
764
+ /**
765
+ * Primitive opzionali che **questo ambiente non serve**, dichiarate dall'ospite (ADR 0020,
766
+ * `contracts.md` §7).
767
+ *
768
+ * Perche' esiste, dato che la rilevazione per identita' del metodo bastava: da quando la
769
+ * libreria spedisce un client HTTP che implementa **tutte** le primitive
770
+ * (`HttpDpeBuilderApi`), chi lo eredita non ha modo di *dis*-sovrascrivere un metodo. Si
771
+ * ritroverebbe comandi attivi su endpoint che il suo backend non serve — esattamente il
772
+ * difetto che la regola dell'identita' esisteva per prevenire.
773
+ *
774
+ * E' **solo sottrattiva**: non rende disponibile cio' che non e' implementato, e il tipo
775
+ * `DpeOptionalPrimitive` le impedisce di nominare le tre primitive obbligatorie. Vuoto per
776
+ * default, cosi' un'implementazione che non la tocca conserva esattamente il comportamento
777
+ * di prima.
778
+ *
779
+ * Chi la usa deve anche rigettare la primitiva con `DpeApiError('MissingService', ...)`
780
+ * **senza emettere la richiesta**: sapere in anticipo che un servizio non c'e' e chiederglielo
781
+ * comunque e' il difetto che questa dichiarazione evita.
782
+ */
783
+ readonly unsupportedPrimitives: readonly DpeOptionalPrimitive[];
784
+ /**
785
+ * `IDpeService.Validate` — **non produce SQL e non legge dati** (`contracts.md` §5). E' la
786
+ * primitiva del feedback durante l'editing: diagnostiche, schemi di ogni nodo, ordine di
787
+ * esecuzione e sequenza dei writeback in una sola risposta.
788
+ *
789
+ * Prende la definizione **in lavorazione**, non quella salvata: cio' che l'editor mostra
790
+ * deve riferirsi a cio' che l'utente sta scrivendo. Va invocata con debounce.
791
+ */
792
+ abstract validate(definition: DpeDefinition): Observable<DpeValidateResult>;
793
+ /**
794
+ * `IDpeService.GetTables` — passaggio diretto al provider di metadati dell'host, **non ai
795
+ * cataloghi del database** (`contracts.md` §2). L'elenco puo' essere grande: chi lo consuma
796
+ * carica in modo asincrono e filtra, non lo riversa in un `<select>`.
797
+ */
798
+ abstract getTables(): Observable<TableSummary[]>;
799
+ /**
800
+ * `IDpeService.GetTable` — i **tre** esiti dell'ADR 0004 restano distinti fino alla UI:
801
+ * `Declared`, `DeclaredWithoutFields` ("la tabella c'e', i campi non li so") e `Unknown`.
802
+ * Appiattirli e' esattamente cio' che il contratto vieta.
803
+ */
804
+ abstract getTable(tableName: string): Observable<TableLookupResult>;
805
+ /**
806
+ * `IDpeService.Compile` — l'anteprima dell'SQL generato, in sola lettura.
807
+ *
808
+ * Opzionale: senza di essa il comando di anteprima si disabilita e il resto dell'editor
809
+ * continua a funzionare.
810
+ *
811
+ * `parameterValues` e' opzionale e corrisponde a `DpeCompileRequest.ParameterValues`.
812
+ * Ometterlo e' un comportamento **dichiarato**, non un ripiego: l'anteprima usa allora i
813
+ * `defaultValue` dei parametri. Passarli serve perche' senza di essi l'anteprima resterebbe
814
+ * muta proprio sui parametri **privi** di default, cioe' quelli che l'utente vuole provare.
815
+ */
816
+ compilePreview(definition: DpeDefinition, parameterValues?: DpeParameterValue[]): Observable<DpeCompileResult>;
817
+ /**
818
+ * Caricamento di una definizione per nome. Opzionale: dove non c'e', l'editor lavora sulla
819
+ * definizione che gli viene passata dall'ospite.
820
+ *
821
+ * La deserializzazione (`IDpeService.Deserialize`) resta del backend: qui arriva un
822
+ * documento già letto, con le sue eventuali diagnostiche già emesse.
823
+ */
824
+ load(name: string): Observable<DpeDefinition>;
825
+ /** Salvataggio. Opzionale: un editor in sola lettura e' un uso legittimo. */
826
+ save(definition: DpeDefinition): Observable<void>;
827
+ /**
828
+ * La dichiarazione dell'ambiente (ADR 0017). Oggi porta **solo** il dialetto del database di
829
+ * destinazione, che e' un fatto dell'installazione e non una preferenza dell'autore della
830
+ * definizione: per questo l'editor non offre nessun comando per cambiarlo.
831
+ *
832
+ * Cosa l'editor fa con la risposta, e cosa non fa: mostra il dialetto in sola lettura e, se
833
+ * differisce da quello della definizione (ADR 0009: e' li' che vive, ed e' da li' che il
834
+ * backend lo legge), **lo segnala senza correggere**. Riscrivere `definition.dialect` sarebbe
835
+ * una migrazione silenziosa di tutte le espressioni SQL native (ADR 0006), per giunta eseguita
836
+ * all'apertura e capace di marcare come «modificata» una definizione che nessuno ha toccato.
837
+ *
838
+ * Opzionale come le altre: dove manca, l'editor mostra il dialetto della definizione e non
839
+ * dice nient'altro.
840
+ */
841
+ getEnvironment(): Observable<DpeEnvironment>;
842
+ /**
843
+ * Elenco delle definizioni disponibili — **catalogo** (ADR 0019). Opzionale: dove manca, un
844
+ * catalogo montato dall'ospite mostra il perche' invece di un elenco vuoto.
845
+ *
846
+ * **Nessun oggetto di interrogazione**, di proposito: niente ricerca, niente paginazione. Il
847
+ * filtro di testo del catalogo e' locale sui sommari ricevuti, e aggiungere una query in
848
+ * seguito e' additivo. Un parametro che nessuno esercita e' un parametro che nessuno verifica.
849
+ *
850
+ * L'ospite e' tenuto a restituire i sommari in un **ordine stabile**: il catalogo non riordina,
851
+ * perche' riordinare lato client combatterebbe una scelta che l'ospite ha gia' fatto.
852
+ */
853
+ listDefinitions(): Observable<DpeDefinitionSummary[]>;
854
+ /**
855
+ * Creazione di una definizione. Opzionale.
856
+ *
857
+ * **Restituisce il sommario, non `void`**: l'ospite puo' aver normalizzato il nome, e chi crea
858
+ * apre **il nome tornato**, non quello digitato. Il risultato di una scrittura non si crede
859
+ * sulla parola.
860
+ *
861
+ * Distinta da `save` per una ragione di merito: `save(definition)` significa «scrivi questa
862
+ * definizione» e non distingue inserimento da aggiornamento, quindi farle significare anche
863
+ * «creala» toglierebbe all'ospite l'unico posto in cui puo' **rifiutare un nome duplicato**.
864
+ *
865
+ * Non esiste una primitiva di duplicazione: duplicare e' `load` piu' `createDefinition`, e il
866
+ * comando vive nel catalogo.
867
+ */
868
+ createDefinition(definition: DpeDefinition): Observable<DpeDefinitionSummary>;
869
+ /**
870
+ * Cancellazione per nome. Opzionale: un catalogo di sola lettura e' un uso legittimo.
871
+ *
872
+ * Non esiste una primitiva di rinomina: rinominare cambia la chiave, quindi e'
873
+ * creare-e-cancellare, cioe' una decisione di storage che e' dell'ospite (ADR 0019).
874
+ */
875
+ deleteDefinition(name: string): Observable<void>;
876
+ }
877
+
878
+ /**
879
+ * Errore categorizzato del contratto verso il backend.
880
+ *
881
+ * L'editor si comporta in base alla **categoria**, mai leggendo il messaggio: chi implementa
882
+ * {@link DpeBuilderApi} traduce l'errore di trasporto (status HTTP, payload, timeout) in un
883
+ * `DpeApiError`, e da lì in poi nella libreria non esiste piu' nessuna nozione di HTTP
884
+ * (ADR 0007).
885
+ */
886
+ /**
887
+ * Le categorie sono **tre** e chiuse, perche' sono tre comportamenti diversi della UI:
888
+ *
889
+ * - `MissingService`: la primitiva non e' implementata su questo ambiente. Degrada il
890
+ * **singolo comando** (l'anteprima SQL si disabilita), non l'editor;
891
+ * - `Transport`: la chiamata non e' arrivata o non e' tornata. Si puo' ritentare;
892
+ * - `Backend`: il backend ha risposto rifiutando. Non si ritenta da soli.
893
+ *
894
+ * Un errore di validazione **non e'** una categoria: le diagnostiche sono un *risultato*
895
+ * (`DpeValidateResult.diagnostics`), non un fallimento — e' la stessa regola del backend,
896
+ * dove il fallimento previsto e' un risultato e non un'eccezione.
897
+ */
898
+ type DpeApiErrorCategory = 'MissingService' | 'Transport' | 'Backend';
899
+ declare class DpeApiError extends Error {
900
+ readonly category: DpeApiErrorCategory;
901
+ /** Payload di dettaglio dell'host, opaco per la libreria. */
902
+ readonly details?: unknown | undefined;
903
+ constructor(category: DpeApiErrorCategory, message: string,
904
+ /** Payload di dettaglio dell'host, opaco per la libreria. */
905
+ details?: unknown | undefined);
906
+ static is(value: unknown): value is DpeApiError;
907
+ /** Vero quando il comando corrispondente va disabilitato invece che segnalato. */
908
+ static isMissingService(value: unknown): boolean;
909
+ }
910
+ /** Messaggi di ripiego: il `message` dell'host, quando c'e', ha la precedenza. */
911
+ declare const DPE_API_ERROR_FALLBACK_MESSAGE: Record<DpeApiErrorCategory, string>;
912
+
913
+ /**
914
+ * Implementazione HTTP di {@link DpeBuilderApi}, sulle rotte **normative** di
915
+ * `docs/contracts.md` §7-bis.
916
+ *
917
+ * Vive nella libreria per decisione del committente (ADR 0020, che revisiona la sola clausola
918
+ * dell'ADR 0007 sulla collocazione): l'integrazione e' due righe invece che un file da copiare.
919
+ * Il prezzo, accettato e scritto: **le rotte sono contratto pubblico**, e cambiarne una e' un
920
+ * breaking change. Da qui in poi questa classe non e' «un esempio» — una classe esportata da una
921
+ * libreria viene usata in produzione a prescindere da come la chiamiamo nel commento, e chiamarla
922
+ * esempio servirebbe solo a esentarla dai test.
923
+ *
924
+ * Resta vero cio' che conta dell'ADR 0007: **il contratto e' la classe astratta**, non questo
925
+ * client. Nessun componente e nessuno store della libreria lo importa. Chi ha rotte diverse ha due
926
+ * strade, e nessuna tocca l'editor:
927
+ *
928
+ * 1. **estendere questa classe** e sovrascrivere i soli metodi divergenti. I punti di estensione
929
+ * sono `protected` di proposito: `url()` per il prefisso e la forma del percorso, `segment()`
930
+ * per la codifica, i quattro verbi per il trasporto, `fail()` per la traduzione degli errori,
931
+ * `request()` per cio' che avvolge ogni chiamata;
932
+ * 2. **scrivere un'altra implementazione di `DpeBuilderApi` da zero** — legittima e supportata.
933
+ *
934
+ * Le tre cose che chi legge questo file deve sapere, e che nessun compilatore gli dira':
935
+ *
936
+ * 1. **il corpo e' il documento nudo** dove il backend analizza o archivia la definizione
937
+ * (`validate`, `createDefinition`, `save`). L'unico involucro e' `compilePreview`, perche' li'
938
+ * il corpo porta anche i valori dei parametri. Sbagliare involucro **non produce nessun
939
+ * errore**: un backend che deserializza una `DpeDefinition` da `{definition: …}` non riconosce
940
+ * nessuna proprieta', risponde `200`, e l'editor mostra la validazione di una definizione
941
+ * vuota;
942
+ * 2. **la serializzazione e' camelCase.** I tipi TypeScript sono allineati a mano ai record C#: un
943
+ * backend che risponde in PascalCase non produce nessun errore, produce campi `undefined`;
944
+ * 3. **l'errore di trasporto diventa una categoria.** L'editor si comporta in base alla categoria
945
+ * e non legge mai il messaggio: `MissingService` disabilita un comando, `Transport` e'
946
+ * ritentabile, `Backend` no.
947
+ *
948
+ * Cosa questo client **non** fa, e non per dimenticanza: nessun `retry`, nessun `shareReplay`,
949
+ * nessuna cache, nessun debounce, nessuna intestazione propria. Traduce trasporto ed errori e
950
+ * nient'altro — la cache vive negli store, il debounce nel chiamante, i tentativi e
951
+ * l'autenticazione negli interceptor dell'ospite. E non tocca `definition.dialect` in nessun
952
+ * metodo (ADR 0009 e 0017): sarebbe una migrazione silenziosa delle espressioni SQL native.
953
+ */
954
+
955
+ /**
956
+ * Configurazione del client. Iniettata e non cablata: in una libreria una costante non e' una
957
+ * scelta, e `const BASE = '/api/dpe'` in un file di libreria toglierebbe all'ospite la sua.
958
+ */
959
+ interface DpeBuilderHttpConfig {
960
+ /** Prefisso comune degli endpoint, es. `/api/dpe` o `https://host/api/dpe`. Senza slash finale. */
961
+ baseUrl?: string;
962
+ /**
963
+ * Primitive opzionali che questo ambiente **non serve** (`contracts.md` §7, dichiarazione
964
+ * sottrattiva). E' l'unico modo che ha l'ospite di spegnere una primitiva che questo client
965
+ * implementa per forza: conoscendo tutti e dieci gli endpoint, li dichiarerebbe altrimenti tutti
966
+ * disponibili, e un comando attivo su un endpoint non servito fallisce alla pressione.
967
+ */
968
+ unsupported?: readonly DpeOptionalPrimitive[];
969
+ }
970
+ declare const DPE_BUILDER_HTTP_CONFIG: InjectionToken<DpeBuilderHttpConfig>;
971
+ declare class HttpDpeBuilderApi extends DpeBuilderApi {
972
+ protected readonly http: HttpClient;
973
+ protected readonly config: DpeBuilderHttpConfig;
974
+ /**
975
+ * Deriva da `DpeBuilderHttpConfig.unsupported`: e' il ponte fra la configurazione e la regola
976
+ * di `contracts.md` §7. Non e' un doppione della configurazione — e' il campo che
977
+ * `core/dpe-capabilities.ts` legge, e leggerlo dal token li' significherebbe portare la
978
+ * configurazione HTTP dentro il calcolo delle capacita'.
979
+ */
980
+ readonly unsupportedPrimitives: readonly DpeOptionalPrimitive[];
981
+ /**
982
+ * Composizione dell'URL. Sovrascriverlo basta a spostare tutte e dieci le rotte sotto un altro
983
+ * prefisso senza toccare un metodo.
984
+ *
985
+ * `?? ''` e non un default: `baseUrl: ''` e' una configurazione **valida** e significa «rotte
986
+ * relative alla radice», quindi non va rimpiazzata dal default del token. Il percorso porta
987
+ * sempre lo slash iniziale, cosi' non nasce un doppio slash.
988
+ */
989
+ protected url(path: string): string;
990
+ /** Codifica di un segmento variabile. Un nome di definizione puo' contenere `/`, spazi, `&`. */
991
+ protected segment(value: string): string;
992
+ /**
993
+ * Cio' che avvolge **ogni** chiamata, e l'unico posto in cui si decide se una chiamata parte.
994
+ *
995
+ * `defer` non e' un vezzo: rende l'`Observable` **freddo** anche per il controllo delle
996
+ * primitive non servite, cosi' chi non sottoscrive non valuta nulla e chi si disiscrive annulla
997
+ * davvero la richiesta HTTP. E' la proprieta' per cui il contratto §7 e' `Observable` e non
998
+ * `Promise` — l'editor la usa per non accumulare validazioni in volo.
999
+ *
1000
+ * Il rigetto per primitiva non servita sta **fuori** dal `catchError`: passandogli dentro, un
1001
+ * `DpeApiError('MissingService')` verrebbe riclassificato `Transport` da `fail()`, che tratta
1002
+ * come guasto di rete tutto cio' che non e' una `HttpErrorResponse`.
1003
+ */
1004
+ protected request<T>(primitive: DpeOptionalPrimitive | string, call: () => Observable<T>): Observable<T>;
1005
+ /** Vero se l'ospite ha dichiarato di non servire questa primitiva. */
1006
+ protected isUnsupported(primitive: string): boolean;
1007
+ /**
1008
+ * Rigetto di una primitiva dichiarata non servita, **senza toccare la rete**: sapere in anticipo
1009
+ * che un servizio non c'e' e chiederglielo comunque e' il difetto che `unsupportedPrimitives`
1010
+ * esiste per evitare, ed e' il motivo per cui il `501` -> `MissingService` non basta da solo.
1011
+ */
1012
+ protected missing(primitive: string): Observable<never>;
1013
+ /**
1014
+ * `501 Not Implemented` diventa `MissingService`: e' cosi' che un ambiente incompleto degrada
1015
+ * **un comando** invece di rompere l'editor. Uno `0` (rete assente, CORS) e' `Transport`, come
1016
+ * qualunque errore che non sia una `HttpErrorResponse`; tutto il resto e' `Backend`.
1017
+ *
1018
+ * Il `404` resta deliberatamente `Backend` e non ha un ramo suo: qui non e' «primitiva assente»
1019
+ * ma «risorsa assente» — una definizione cancellata da altri, un nome che non esiste piu'. Chi
1020
+ * volesse distinguerlo lo mappi su una categoria propria, non su `MissingService`: disabilitare
1021
+ * un comando perche' un singolo nome non e' stato trovato sarebbe la reazione sbagliata.
1022
+ *
1023
+ * Il messaggio si prende in ordine — corpo dell'errore, messaggio della risposta, ripiego che
1024
+ * nomina la primitiva — e serve solo all'umano: l'editor guarda la categoria.
1025
+ */
1026
+ protected fail(error: unknown, primitive: string): Observable<never>;
1027
+ protected httpGet<T>(path: string): Observable<T>;
1028
+ protected httpPost<T>(path: string, body: unknown): Observable<T>;
1029
+ protected httpPut<T>(path: string, body: unknown): Observable<T>;
1030
+ protected httpDelete<T>(path: string): Observable<T>;
1031
+ validate(definition: DpeDefinition): Observable<DpeValidateResult>;
1032
+ getTables(): Observable<TableSummary[]>;
1033
+ getTable(tableName: string): Observable<TableLookupResult>;
1034
+ /** L'**unica** rotta con involucro: il corpo porta anche i valori dei parametri (§7-bis). */
1035
+ compilePreview(definition: DpeDefinition, parameterValues?: DpeParameterValue[]): Observable<DpeCompileResult>;
1036
+ load(name: string): Observable<DpeDefinition>;
1037
+ save(definition: DpeDefinition): Observable<void>;
1038
+ /**
1039
+ * La dichiarazione dell'ambiente (ADR 0017). Questo client la implementa perche' conosce
1040
+ * l'endpoint, non perche' sappia se l'ospite lo serve — ed e' precisamente la ragione per cui
1041
+ * l'ADR 0020 ha aggiunto `unsupportedPrimitives`.
1042
+ *
1043
+ * Non e' un dettaglio: l'abilitazione della creazione nel catalogo (ADR 0019) dipende da questa
1044
+ * primitiva, quindi un ambiente che non la serve deve lasciare il comando disabilitato **con il
1045
+ * motivo**. Da qui i **tre** rami, che sono tre cose diverse e vanno tenute distinte:
1046
+ *
1047
+ * - **primitiva non implementata**: il metodo non viene sovrascritto, e il `MissingService` lo
1048
+ * produce l'identita' stessa del metodo. E' la strada di chi scrive la propria
1049
+ * implementazione di `DpeBuilderApi`, non di chi eredita questo client;
1050
+ * - **primitiva implementata ma non servita da questo ambiente**: e' il ramo centrale, quello
1051
+ * che questo file rende necessario. L'ospite mette `'getEnvironment'` in
1052
+ * `DpeBuilderHttpConfig.unsupported`, il comando resta disabilitato con il motivo, e **nessuna
1053
+ * richiesta parte**. Un metodo ereditato non si puo' dis-sovrascrivere: senza questa
1054
+ * dichiarazione il comando risulterebbe attivo;
1055
+ * - **primitiva servita che fallisce**: l'endpoint risponde male, e l'errore e' `Transport` o
1056
+ * `Backend`. Un ambiente rotto, non un ambiente incompleto.
1057
+ *
1058
+ * Rispondere `501` da questo endpoint per significare «non lo dichiaro» arriva allo stesso posto
1059
+ * nel modo sbagliato: costa un giro di rete a ogni apertura dell'editor per comunicare un fatto
1060
+ * che si conosce a tempo di configurazione.
1061
+ *
1062
+ * Cio' che l'editor fa della risposta resta suo: mostra il dialetto in sola lettura e segnala
1063
+ * senza correggere se differisce da quello della definizione.
1064
+ */
1065
+ getEnvironment(): Observable<DpeEnvironment>;
1066
+ /** Nessun parametro di interrogazione: il filtro del catalogo e' locale, di proposito. */
1067
+ listDefinitions(): Observable<DpeDefinitionSummary[]>;
1068
+ /**
1069
+ * `POST` e non `PUT`: e' una **creazione**, quindi il backend puo' rifiutare un nome duplicato —
1070
+ * ed e' l'unica ragione per cui questa primitiva esiste separata da `save`. La risposta e' il
1071
+ * **sommario**, che chi crea deve adottare: il nome puo' essere stato normalizzato.
1072
+ */
1073
+ createDefinition(definition: DpeDefinition): Observable<DpeDefinitionSummary>;
1074
+ deleteDefinition(name: string): Observable<void>;
1075
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<HttpDpeBuilderApi, never>;
1076
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<HttpDpeBuilderApi>;
1077
+ }
1078
+ /**
1079
+ * Registra il client e la sua configurazione: l'integrazione in una riga che l'ADR 0020 chiedeva.
1080
+ *
1081
+ * **Non** chiama `provideHttpClient()`, e non e' una dimenticanza: il backend (`withFetch`), gli
1082
+ * interceptor, l'autenticazione e i cookie sono scelte dell'applicazione ospite, e una libreria
1083
+ * che le prende al posto suo la costringe a disfarle.
1084
+ *
1085
+ * `baseUrl` omesso ricade sul default, `baseUrl: ''` **no**: la stringa vuota e' una
1086
+ * configurazione valida («rotte relative alla radice») e un `||` la scambierebbe per assente.
1087
+ */
1088
+ declare function provideDpeBuilderHttpApi(config?: DpeBuilderHttpConfig): EnvironmentProviders;
1089
+
1090
+ declare class DpeCatalogStore {
1091
+ private readonly api;
1092
+ private readonly destroyRef;
1093
+ /**
1094
+ * Le primitive disponibili, fotografate **alla costruzione** per identita' del metodo
1095
+ * (`dpe-capabilities.ts`). La disponibilita' si sa prima del clic: un comando che sembra attivo
1096
+ * e fallisce alla pressione insegna a non fidarsi dei bottoni.
1097
+ */
1098
+ readonly capabilities: _esfaenza_dpe_builder.DpeCapabilities;
1099
+ /** Il comando di creazione dipende da **due** primitive, e il motivo va mostrato. */
1100
+ readonly createCommand: _esfaenza_dpe_builder.DpeCommandAvailability;
1101
+ private readonly _summaries;
1102
+ private readonly _isLoading;
1103
+ private readonly _isMutating;
1104
+ private readonly _error;
1105
+ private readonly _hasLoaded;
1106
+ private readonly _environmentDialect;
1107
+ /** Nell'ordine restituito dall'ospite, mai riordinato. */
1108
+ readonly summaries: _angular_core.Signal<readonly DpeDefinitionSummary[]>;
1109
+ /**
1110
+ * Due stati distinti e non uno: **elencare** e **scrivere** si vedono diversi. Un unico
1111
+ * "occupato" farebbe lampeggiare l'elenco a ogni cancellazione, e nasconderebbe il fatto che
1112
+ * dopo una scrittura l'elenco si ricarica.
1113
+ */
1114
+ readonly isLoading: _angular_core.Signal<boolean>;
1115
+ readonly isMutating: _angular_core.Signal<boolean>;
1116
+ readonly error: _angular_core.Signal<DpeApiError | null>;
1117
+ /** Vero dopo la prima risposta: prima, un elenco vuoto non significa «nessuna definizione». */
1118
+ readonly hasLoaded: _angular_core.Signal<boolean>;
1119
+ /**
1120
+ * Il dialetto **dichiarato dall'ambiente** (ADR 0017), che e' quello con cui nasce una
1121
+ * definizione creata da qui. Non si chiede all'utente e non si sceglie per ripiego: senza
1122
+ * dichiarazione il comando di creazione resta spento (`createCommand`).
1123
+ */
1124
+ readonly environmentDialect: _angular_core.Signal<SqlDialectKind | undefined>;
1125
+ readonly isEmpty: _angular_core.Signal<boolean>;
1126
+ constructor();
1127
+ /**
1128
+ * Ricarica l'elenco. Senza `listDefinitions` non e' un errore: e' un ambiente che non offre il
1129
+ * catalogo, e chi rende lo dice guardando `capabilities.listDefinitions`.
1130
+ */
1131
+ refresh(): void;
1132
+ /**
1133
+ * Crea una definizione **subito**, non al primo salvataggio: `save` significa «scrivi questa
1134
+ * definizione» e non distingue inserimento da aggiornamento, quindi solo `createDefinition` da'
1135
+ * all'ospite il punto in cui rifiutare un nome duplicato. Una definizione che esiste solo nel
1136
+ * browser e' inoltre uno stato che l'elenco non puo' mostrare.
1137
+ *
1138
+ * Il dialetto arriva dall'ambiente e non dall'utente (ADR 0017): lo passa il chiamante, che lo
1139
+ * legge da `environmentDialect`.
1140
+ *
1141
+ * L'osservabile e' **freddo**: chi comanda si iscrive **una volta** e riceve il sommario che
1142
+ * l'ospite ha restituito — non quello costruito qui, perche' il nome puo' essere stato
1143
+ * normalizzato.
1144
+ */
1145
+ create(name: string, label: string, dialect: SqlDialectKind): Observable<DpeDefinitionSummary>;
1146
+ /**
1147
+ * Duplica: `load` **e poi** `createDefinition`. Non esiste una primitiva di duplicazione sul
1148
+ * contratto, e non deve esistere — si comporrebbe di queste due comunque, e una primitiva
1149
+ * dedicata dovrebbe ridecidere lato host cosa cambia.
1150
+ *
1151
+ * Il dialetto e' quello della **definizione di partenza**, non quello dell'ambiente: le
1152
+ * espressioni sono SQL nativo (ADR 0006) e cambiare dialetto duplicando sarebbe una migrazione
1153
+ * silenziosa.
1154
+ */
1155
+ duplicate(sourceName: string, name: string, label: string): Observable<DpeDefinitionSummary>;
1156
+ /** Cancella per nome e ricarica l'elenco. La conferma e' della schermata, non dello store. */
1157
+ remove(name: string): void;
1158
+ dismissError(): void;
1159
+ /**
1160
+ * Il tratto comune delle due scritture: stato di attesa, **`refresh` dopo il successo** — un
1161
+ * elenco che omette cio' che l'utente ha appena creato e' un elenco che mente — ed errore nel
1162
+ * signal invece che propagato. Chi comanda non deve trattare l'errore due volte.
1163
+ */
1164
+ private mutate;
1165
+ /** Un errore del provider finisce in `error()` e **non lancia**: nessuno lo raccoglierebbe. */
1166
+ private fail;
1167
+ /** Cio' che l'host non categorizza diventa `Transport`, la categoria "riprovabile". */
1168
+ private toApiError;
1169
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeCatalogStore, never>;
1170
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<DpeCatalogStore>;
1171
+ }
1172
+
1173
+ /**
1174
+ * Il grafo della definizione: **un solo posto** costruisce gli id di nodi, porte e archi, e
1175
+ * **un solo elenco** descrive dove vivono i riferimenti fra nodi.
1176
+ *
1177
+ * Perche' sta tutto qui. Un id di porta costruito in due modi diversi (canvas da un lato,
1178
+ * derivazione degli archi dall'altro) fa sparire un arco **senza nessun errore**: e' il
1179
+ * difetto piu' difficile da trovare in un editor a canvas. Allo stesso modo, un riferimento
1180
+ * dimenticato nell'elenco degli slot fa restare incoerente il documento dopo una rinomina,
1181
+ * anche lì in silenzio.
1182
+ *
1183
+ * Cosa **non** sta qui: nessuna regola di dominio. Questo file dice *dove* stanno i nomi dei
1184
+ * nodi a monte, non se un riferimento e' valido, se il grafo ha cicli (**I2**), se un nodo e'
1185
+ * a valle (**I3**) o quali colonne produca (**I4**). Quelle risposte arrivano da
1186
+ * `DpeBuilderApi.validate`.
1187
+ */
1188
+
1189
+ declare function dpeNodeId(nodeName: string): string;
1190
+ /**
1191
+ * Porta di ingresso. Una porta **per slot** (e per indice, sugli slot a lista): un `JoinNode`
1192
+ * ha due ingressi distinti e attaccare l'arco alla porta sbagliata scambia primaria e
1193
+ * secondaria, che e' un join diverso.
1194
+ */
1195
+ declare function dpeInputPortId(nodeName: string, slot: string, index?: number): string;
1196
+ /** Porta di uscita: una sola per nodo, lo schema prodotto e' uno. */
1197
+ declare function dpeOutputPortId(nodeName: string): string;
1198
+ /**
1199
+ * Id dell'arco: identifica la **destinazione** (nodo, slot, indice), non la coppia di nodi.
1200
+ * Due archi possono unire gli stessi due nodi su slot diversi — la primaria e la secondaria
1201
+ * di un self-join — e con un id per coppia uno dei due sparirebbe.
1202
+ */
1203
+ declare function dpeEdgeId(targetNodeName: string, slot: string, index?: number): string;
1204
+ /**
1205
+ * Gli inversi. Stanno **accanto** ai costruttori e non nel canvas: la libreria di canvas
1206
+ * restituisce gli id nei suoi eventi, e chi li legge deve tornare al nome del nodo con la
1207
+ * stessa convenzione con cui li ha scritti. Separarli e' il modo con cui un giorno cambierebbe
1208
+ * uno solo dei due.
1209
+ */
1210
+ declare function dpeParseNodeId(id: string): string | undefined;
1211
+ declare function dpeParseOutputPortId(id: string): string | undefined;
1212
+ declare function dpeParseInputPortId(id: string): {
1213
+ nodeName: string;
1214
+ slot: string;
1215
+ index?: number;
1216
+ } | undefined;
1217
+ /**
1218
+ * Uno slot e' un punto del nodo che contiene il nome di **un altro nodo**.
1219
+ *
1220
+ * `read` e `write` sono **posizionali e di lunghezza stabile**: `write(node, read(node))` non
1221
+ * cambia il nodo. E' la proprieta' che permette di implementare la rinomina come
1222
+ * `write(node, read(node).map(rinomina))` — cioe' con un solo cammino di codice, invece di
1223
+ * due elenchi (uno per leggere gli archi, uno per rinominare) che al primo campo aggiunto
1224
+ * diventano due elenchi diversi.
1225
+ */
1226
+ interface DpeSourceSlot<TNode> {
1227
+ readonly slot: string;
1228
+ /**
1229
+ * `true` quando lo slot e' un **arco del DAG** (il flusso dei dati). `false` per i
1230
+ * riferimenti che sono altro: i `sourceName` dei `JoinResultField` ripetono le sorgenti del
1231
+ * join, e le relazioni di un gruppo atomico dichiarano una transazione dell'host, non un
1232
+ * flusso di dati (l'ordinamento dei sink e' esplicito e separato dal DAG).
1233
+ */
1234
+ readonly isEdge: boolean;
1235
+ read(node: TNode): readonly (string | undefined)[];
1236
+ write(node: TNode, names: readonly (string | undefined)[]): TNode;
1237
+ }
1238
+ /** Gli slot di ogni collezione. Aggiungere un nodo significa aggiungere una riga qui. */
1239
+ declare const DPE_SOURCE_SLOTS: {
1240
+ readonly [K in DpeNodeCollectionName]: readonly DpeSourceSlot<DpeNodeCollectionMap[K]>[];
1241
+ };
1242
+ /** Un nodo con la collezione da cui viene: senza, non si sa quali slot leggere. */
1243
+ interface DpeLocatedNode<K extends DpeNodeCollectionName = DpeNodeCollectionName> {
1244
+ collection: K;
1245
+ index: number;
1246
+ node: DpeNodeCollectionMap[K];
1247
+ }
1248
+ /** Tutti i nodi, nell'ordine delle collezioni (sorgenti -> trasformazioni -> sink). */
1249
+ declare function dpeAllNodes(definition: DpeDefinition): DpeLocatedNode[];
1250
+ declare function dpeFindNode(definition: DpeDefinition, nodeName: string): DpeLocatedNode | undefined;
1251
+ interface DpeSourceReference {
1252
+ /** Nodo che contiene il riferimento (la destinazione dell'arco). */
1253
+ targetNodeName: string;
1254
+ collection: DpeNodeCollectionName;
1255
+ slot: string;
1256
+ /** Presente solo sugli slot a lista. */
1257
+ index?: number;
1258
+ isEdge: boolean;
1259
+ /** Nome riferito; assente quando lo slot e' vuoto (nodo non collegato). */
1260
+ sourceName?: string;
1261
+ }
1262
+ /** I riferimenti di un singolo nodo, in ordine di slot. */
1263
+ declare function dpeNodeSourceReferences(located: DpeLocatedNode): DpeSourceReference[];
1264
+ interface DpeGraphNode {
1265
+ id: string;
1266
+ name: string;
1267
+ collection: DpeNodeCollectionName;
1268
+ outputPortId: string;
1269
+ }
1270
+ interface DpeGraphEdge {
1271
+ id: string;
1272
+ /** Nome del nodo a monte, come scritto nel documento. */
1273
+ fromNodeName: string;
1274
+ toNodeName: string;
1275
+ slot: string;
1276
+ index?: number;
1277
+ fromPortId: string;
1278
+ toPortId: string;
1279
+ /**
1280
+ * `false` quando il nome a monte non corrisponde a nessun nodo della definizione. L'arco
1281
+ * **si mostra comunque**: la topologia mostrata e' quella reale, e un riferimento rotto va
1282
+ * visto, non nascosto. La diagnostica che lo qualifica (`DPE_REF_UNKNOWN_NODE`) arriva dal
1283
+ * backend.
1284
+ */
1285
+ isResolved: boolean;
1286
+ }
1287
+ interface DpeGraph {
1288
+ nodes: DpeGraphNode[];
1289
+ edges: DpeGraphEdge[];
1290
+ }
1291
+ /**
1292
+ * Deriva nodi e archi dalla definizione, per riferimento di nome. Funzione pura: nessuna
1293
+ * lettura di stato, nessuna dipendenza da Angular, testabile senza DOM.
1294
+ */
1295
+ declare function dpeBuildGraph(definition: DpeDefinition): DpeGraph;
1296
+ /** Le porte di ingresso di un nodo, nell'ordine in cui vanno disegnate. */
1297
+ interface DpeInputPort {
1298
+ id: string;
1299
+ slot: string;
1300
+ index?: number;
1301
+ /** Nome collegato, assente se la porta e' libera. */
1302
+ sourceName?: string;
1303
+ }
1304
+ declare function dpeInputPorts(located: DpeLocatedNode): DpeInputPort[];
1305
+ /**
1306
+ * Riscrive un riferimento in **uno** slot di **un** nodo. E' il mattone di `connect` e
1307
+ * `disconnect` dello store: passando `undefined` la porta torna libera.
1308
+ */
1309
+ declare function dpeWriteSourceReference<K extends DpeNodeCollectionName>(collection: K, node: DpeNodeCollectionMap[K], slotName: string, index: number | undefined, sourceName: string | undefined): DpeNodeCollectionMap[K];
1310
+ /**
1311
+ * **Rinominare un nodo e' un refactoring globale, non locale** (**I5**).
1312
+ *
1313
+ * Questa e' l'unica funzione che rinomina: aggiorna il `name` del nodo e **ogni** riferimento
1314
+ * a valle, passando dall'unico elenco di slot — `sourceName`, `sources`,
1315
+ * `primarySourceName`/`secondarySourceName`, i `sourceName` dei `JoinResultField` e i nomi
1316
+ * dentro i gruppi atomici. Se una collezione di riferimenti sfuggisse, il documento
1317
+ * diventerebbe silenziosamente incoerente: e' il difetto che questa funzione esiste per non
1318
+ * avere.
1319
+ *
1320
+ * Cosa **non** fa, di proposito: non rinomina gli **alias di colonna** (sono un altro spazio
1321
+ * di nomi) e non decide se il nuovo nome sia lecito o già usato — l'unicita' e' **I1**, la
1322
+ * verifica il backend.
1323
+ *
1324
+ * Il confronto e' **esatto**, non case-insensitive: `domain-model.md` dichiara il confronto
1325
+ * `OrdinalIgnoreCase` per gli **alias di colonna** e non dice nulla sui nomi dei nodi.
1326
+ * Rinominare anche le occorrenze con capitalizzazione diversa significherebbe, se il backend
1327
+ * risolvesse i nomi in modo esatto, riscrivere il riferimento a un nodo **diverso**.
1328
+ */
1329
+ declare function dpeRenameNode(definition: DpeDefinition, oldName: string, newName: string): DpeDefinition;
1330
+ /** Quante occorrenze toccherebbe una rinomina: serve a dirlo prima, non dopo. */
1331
+ declare function dpeCountReferences(definition: DpeDefinition, nodeName: string): number;
1332
+
1333
+ /**
1334
+ * Utility pure sulle diagnostiche **ricevute** dal backend: raggruppamento per nodo, gravita'
1335
+ * peggiore, e la distinzione fra "da correggere" e "non ancora compilabile".
1336
+ *
1337
+ * Qui non nasce nessuna diagnostica e non si giudica nessuna definizione: si legge cio' che il
1338
+ * backend ha detto e si decide **come renderlo**. La sola informazione interpretata e' il
1339
+ * `DiagnosticPath`, che il contratto pubblica in **due forme** (con nome del nodo dalla
1340
+ * validazione, con solo indice dalla deserializzazione): chi legge deve accettarle entrambe,
1341
+ * altrimenti le diagnostiche del caricamento di un file non sono navigabili.
1342
+ */
1343
+
1344
+ /**
1345
+ * Il nodo a cui una diagnostica si riferisce, se ricavabile.
1346
+ *
1347
+ * Tre strade, nell'ordine: il nome nel primo segmento del percorso; l'argomento canonico
1348
+ * `node`; l'indice del primo segmento risolto nella collezione corrispondente della
1349
+ * definizione — che e' il caso della deserializzazione, dove i nomi non sono ancora noti.
1350
+ * Senza la terza, un `filters[0].sourceName` resterebbe una riga non cliccabile.
1351
+ */
1352
+ declare function dpeDiagnosticNodeName(diagnostic: Diagnostic, definition?: DpeDefinition): string | undefined;
1353
+ /** Il campo in causa, per evidenziarlo nell'ispettore. */
1354
+ declare function dpeDiagnosticField(diagnostic: Diagnostic): string | undefined;
1355
+ /**
1356
+ * `true` per l'unico codice che significa "hai fatto bene, siamo noi" (**I10**, ADR 0005):
1357
+ * `Forecast`, `CustomNode`, costrutto non supportato dal dialetto scelto. Non va mescolato
1358
+ * con i `DPE_MODEL_*`, che l'utente deve correggere.
1359
+ */
1360
+ declare function dpeIsNotCompilable(diagnostic: Diagnostic): boolean;
1361
+ /**
1362
+ * `true` quando la diagnostica riguarda le **capacita' del dialetto** e non la definizione in
1363
+ * se': l'interfaccia deve dire «questo dialetto non lo supporta», perche' lo stesso documento
1364
+ * su un altro dialetto sarebbe compilabile.
1365
+ */
1366
+ declare function dpeIsDialectDiagnostic(diagnostic: Diagnostic): boolean;
1367
+ interface DpeNodeDiagnostics {
1368
+ /** Diagnostiche ancorate al nodo, nell'ordine ricevuto (**I6**: l'elenco e' esaustivo). */
1369
+ diagnostics: Diagnostic[];
1370
+ /** La gravita' peggiore fra quelle presenti. */
1371
+ severity?: DiagnosticSeverity;
1372
+ /**
1373
+ * Il nodo e' **valido ma non compilabile**: stato distinto da "non valido", e l'unico per
1374
+ * cui la UI non deve chiedere all'utente di correggere niente.
1375
+ */
1376
+ isNotCompilable: boolean;
1377
+ }
1378
+ declare function dpeWorstSeverity(diagnostics: readonly Diagnostic[]): DiagnosticSeverity | undefined;
1379
+ /** Raggruppa per nodo. Le diagnostiche non ancorabili a un nodo non si perdono: vedi sotto. */
1380
+ declare function dpeGroupDiagnosticsByNode(diagnostics: readonly Diagnostic[], definition?: DpeDefinition): Map<string, DpeNodeDiagnostics>;
1381
+ /**
1382
+ * Le diagnostiche che **non** appartengono a nessun nodo (radice, parametri, sequenza dei
1383
+ * writeback, grafo intero). Esistono come funzione a se' perche' il pannello deve mostrarle:
1384
+ * un `DPE_GRAPH_NO_WRITEBACK` che scompare perche' non ha un nodo a cui attaccarsi sarebbe la
1385
+ * diagnostica piu' importante di tutte a non arrivare all'utente.
1386
+ */
1387
+ declare function dpeDefinitionLevelDiagnostics(diagnostics: readonly Diagnostic[], definition?: DpeDefinition): Diagnostic[];
1388
+ /** Testo leggibile del percorso, per la riga del pannello. */
1389
+ declare function dpeDiagnosticLocationLabel(diagnostic: Diagnostic, definition?: DpeDefinition): string;
1390
+ /** I nomi dei nodi presenti nella definizione: serve a chi naviga dal pannello al canvas. */
1391
+ declare function dpeKnownNodeNames(definition: DpeDefinition): Set<string>;
1392
+
1393
+ /**
1394
+ * Le coordinate di un nodo sul canvas — ADR 0013.
1395
+ *
1396
+ * Vivono in `extensionData` sotto la chiave namespaced `dpe:layout`, forma `{x, y}`. Il
1397
+ * backend le conserva senza interpretarle (**I7**), la validazione non le guarda, il
1398
+ * compilatore non le vede: l'unico livello che gli da' significato e' l'editor.
1399
+ *
1400
+ * Due regole dell'ADR sono implementate qui, e sono le sole che contano:
1401
+ *
1402
+ * - le coordinate sono **opzionali**: una definizione scritta a mano non le ha e resta
1403
+ * valida; in loro assenza si esegue dagre;
1404
+ * - un `dpe:layout` **malformato o parziale si ignora**. Un documento arrivato da un'altra
1405
+ * versione non deve poter rompere il canvas, e "meta' coordinata" non e' una posizione:
1406
+ * accettarla metterebbe il nodo a `x` giusta e `y` zero, cioe' in un posto che nessuno ha
1407
+ * scelto.
1408
+ */
1409
+
1410
+ /** La chiave e' namespaced perche' `extensionData` e' anche dove atterrano i campi futuri. */
1411
+ declare const DPE_LAYOUT_KEY = "dpe:layout";
1412
+ interface DpeNodePosition {
1413
+ x: number;
1414
+ y: number;
1415
+ }
1416
+ /** Legge la posizione, oppure `undefined` se assente o non utilizzabile. */
1417
+ declare function dpeReadNodePosition(node: DpeAnyNode): DpeNodePosition | undefined;
1418
+ /** Scrive la posizione producendo un nuovo nodo: il documento resta immutabile. */
1419
+ declare function dpeWriteNodePosition<TNode extends DpeAnyNode>(node: TNode, position: DpeNodePosition): TNode;
1420
+ /** Vero quando **tutti** i nodi hanno una posizione: se no, il canvas rifa' il layout. */
1421
+ declare function dpeHasCompleteLayout(nodes: readonly DpeAnyNode[]): boolean;
1422
+
1423
+ /** Una definizione vuota ma **leggibile**: `formatVersion` e `dialect` non sono opzionali. */
1424
+ declare function dpeEmptyDefinition(name: string, label: string, dialect: SqlDialectKind): DpeDefinition;
1425
+ declare class DpeDocumentStore {
1426
+ private readonly _definition;
1427
+ private readonly _validateResult;
1428
+ private readonly _compileResult;
1429
+ /**
1430
+ * I nodi selezionati, in ordine di gesto. E' una **lista** e non un nome singolo perche' il
1431
+ * canvas sa selezionare piu' nodi (riquadro, `Ctrl+A`) e trascinarli insieme: tenere qui un solo
1432
+ * nome costringerebbe la libreria a conservare gli altri, cioe' a essere di nuovo autorevole
1433
+ * sulla selezione.
1434
+ */
1435
+ private readonly _selectedNodeNames;
1436
+ private readonly _past;
1437
+ private readonly _future;
1438
+ /**
1439
+ * Istantanea di riferimento: l'ultimo stato **salvato**. Non e' un contatore di operazioni.
1440
+ * Contare le mutazioni sembra equivalente e non lo e': dopo un `undo` il contatore sale, cioe'
1441
+ * dichiara piu' modifiche di prima proprio quando l'utente ne ha disfatta una. Serve a decidere
1442
+ * se salvare, quindi deve rispondere alla domanda giusta — "differisce da cio' che e' salvato?"
1443
+ * — e tornare a "no" quando si annulla fino allo stato di partenza.
1444
+ */
1445
+ private readonly _savedSnapshot;
1446
+ /** La definizione corrente: unica fonte di verita' per canvas, ispettori e pannelli. */
1447
+ readonly definition: _angular_core.Signal<DpeDefinition>;
1448
+ /** Nodi e archi derivati dalla definizione. Ricalcolati solo quando la definizione cambia. */
1449
+ readonly graph: _angular_core.Signal<DpeGraph>;
1450
+ readonly selectedNodeNames: _angular_core.Signal<readonly string[]>;
1451
+ /** Insieme dei selezionati: il canvas lo interroga una volta per nodo a ogni render. */
1452
+ readonly selectedNodeNameSet: _angular_core.Signal<ReadonlySet<string>>;
1453
+ /**
1454
+ * Il nodo che l'ispettore mostra: il **primo** della selezione. Un ispettore per piu' nodi
1455
+ * insieme mostrerebbe campi che appartengono a nodi diversi, che e' peggio di non mostrarne.
1456
+ */
1457
+ readonly selectedNodeName: _angular_core.Signal<string | undefined>;
1458
+ readonly selectedNode: _angular_core.Signal<DpeAnyNode | undefined>;
1459
+ readonly validateResult: _angular_core.Signal<DpeValidateResult | undefined>;
1460
+ readonly compileResult: _angular_core.Signal<DpeCompileResult | undefined>;
1461
+ readonly diagnostics: _angular_core.Signal<readonly Diagnostic[]>;
1462
+ readonly schemas: _angular_core.Signal<readonly DpeNodeSchemaInfo[]>;
1463
+ readonly executionOrder: _angular_core.Signal<readonly string[]>;
1464
+ readonly writebackSequence: _angular_core.Signal<readonly DpeWritebackStep[]>;
1465
+ /** Schema per nome di nodo: la vista dello schema lo cerca per nodo, non per posizione. */
1466
+ readonly schemaByNode: _angular_core.Signal<ReadonlyMap<string, DpeNodeSchemaInfo>>;
1467
+ /**
1468
+ * Diagnostiche raggruppate per nodo, piu' quelle che **non** appartengono a nessun nodo
1469
+ * (radice, parametri, grafo intero): tenerle separate e' l'unico modo perche' un
1470
+ * `DPE_GRAPH_NO_WRITEBACK` non scompaia solo perche' non ha un nodo a cui attaccarsi.
1471
+ */
1472
+ readonly diagnosticsByNode: _angular_core.Signal<ReadonlyMap<string, DpeNodeDiagnostics>>;
1473
+ readonly definitionDiagnostics: _angular_core.Signal<readonly Diagnostic[]>;
1474
+ /** Posizioni lette da `dpe:layout` (ADR 0013): assenti dove il documento non le porta. */
1475
+ readonly positions: _angular_core.Signal<ReadonlyMap<string, DpeNodePosition>>;
1476
+ readonly canUndo: _angular_core.Signal<boolean>;
1477
+ readonly canRedo: _angular_core.Signal<boolean>;
1478
+ /**
1479
+ * Vero quando il documento differisce dall'ultimo salvataggio. Il confronto e' fra istantanee
1480
+ * JSON — la stessa moneta dell'undo/redo — e **non** un conteggio di differenze: un elenco di
1481
+ * differenze costa quanto un diff strutturale, e nessuno lo legge come numero.
1482
+ *
1483
+ * Confronto testuale, quindi sensibile all'ordine delle chiavi. Le mutazioni producono nuovi
1484
+ * valori per spread, che l'ordine lo conserva, e l'undo riparte dalla stessa serializzazione:
1485
+ * l'unico esito possibile di una divergenza d'ordine sarebbe un falso "modificata", cioe' un
1486
+ * salvataggio in piu' e mai una perdita.
1487
+ */
1488
+ readonly isDirty: _angular_core.Signal<boolean>;
1489
+ /**
1490
+ * Sostituisce la definizione. Azzera la cronologia: le istantanee della definizione
1491
+ * precedente non sono passi di quella nuova, e un undo che riportasse a un altro documento
1492
+ * sarebbe una perdita di dati che l'utente non ha chiesto.
1493
+ */
1494
+ load(definition: DpeDefinition): void;
1495
+ /** Deposita il risultato della validazione. Nessuna interpretazione: si mostra cio' che c'e'. */
1496
+ applyValidateResult(result: DpeValidateResult | undefined): void;
1497
+ applyCompileResult(result: DpeCompileResult | undefined): void;
1498
+ /**
1499
+ * L'ospite ha salvato: da qui in poi il riferimento e' il documento **effettivamente
1500
+ * persistito**, che si passa come argomento.
1501
+ *
1502
+ * Il parametro non e' un vezzo: un salvataggio e' asincrono, e nel frattempo l'utente puo'
1503
+ * avere continuato a scrivere. Fissando il riferimento sullo stato *corrente* si dichiarerebbe
1504
+ * salvato anche cio' che e' stato scritto dopo l'invio, cioe' esattamente il lavoro che si
1505
+ * perderebbe. Omesso, vale lo stato corrente: e' il caso di chi salva in modo sincrono.
1506
+ */
1507
+ markSaved(saved?: DpeDefinition): void;
1508
+ /**
1509
+ * **L'unico** punto che decide quale nodo e' selezionato. La selezione ha una sola fonte di
1510
+ * verita', come la definizione: la classe nel DOM e lo stato di selezione della libreria di
1511
+ * canvas ne **derivano**, non la stabiliscono. Due scritture indipendenti sullo stesso fatto
1512
+ * producono due nodi selezionati insieme e un utente che non sa su cosa sta agendo.
1513
+ */
1514
+ select(nodeName: string | undefined): void;
1515
+ /** Selezione multipla (riquadro, `Ctrl+A`): la lista che arriva dal gesto, senza duplicati. */
1516
+ selectMany(nodeNames: readonly string[]): void;
1517
+ /** Proprieta' della radice: etichetta, descrizione, dialetto, parametri. */
1518
+ patchDefinition(patch: Partial<DpeDefinition>): void;
1519
+ addNode<K extends DpeNodeCollectionName>(collection: K, node: DpeNodeCollectionMap[K]): void;
1520
+ updateNode<K extends DpeNodeCollectionName>(collection: K, nodeName: string, patch: Partial<DpeNodeCollectionMap[K]>): void;
1521
+ /**
1522
+ * Rimuove un nodo. I riferimenti a valle **restano** e diventano riferimenti rotti: e' cio'
1523
+ * che il documento dice davvero, e il backend li segnala (`DPE_REF_UNKNOWN_NODE`). Pulirli
1524
+ * qui vorrebbe dire decidere al posto dell'utente che quel filtro non serve piu'.
1525
+ */
1526
+ removeNode(nodeName: string): void;
1527
+ /**
1528
+ * L'**unico** punto che rinomina un nodo (**I5**): delega alla funzione pura, che aggiorna
1529
+ * ogni riferimento a valle passando dall'unico elenco di slot.
1530
+ */
1531
+ renameNode(oldName: string, newName: string): void;
1532
+ /** Quante occorrenze toccherebbe una rinomina: si dice prima, non dopo. */
1533
+ countReferences(nodeName: string): number;
1534
+ /**
1535
+ * Crea un nodo della categoria data nella posizione indicata e restituisce il nome
1536
+ * assegnato, cosi' chi lo ha creato puo' selezionarlo subito.
1537
+ */
1538
+ createNodeAt<K extends DpeNodeCollectionName>(collection: K, position: DpeNodePosition): string;
1539
+ /**
1540
+ * Sposta un nodo scrivendo `dpe:layout`. `silent` non aggiunge un passo di cronologia:
1541
+ * trascinare cinque nodi insieme e' **un** gesto, e cinque passi di undo per un solo
1542
+ * trascinamento sono cinque passi che l'utente non ha fatto.
1543
+ */
1544
+ moveNode(nodeName: string, position: DpeNodePosition, options?: {
1545
+ silent?: boolean;
1546
+ }): void;
1547
+ /**
1548
+ * Applica un layout calcolato **su comando dell'utente** («Riordina»): un passo di cronologia
1549
+ * per l'intero riordino, e il documento risulta modificato, perche' lo e'.
1550
+ */
1551
+ applyPositions(positions: ReadonlyMap<string, DpeNodePosition>): void;
1552
+ /**
1553
+ * Layout **iniziale** di un documento che non porta coordinate (ADR 0013: sono opzionali).
1554
+ *
1555
+ * Non e' una modifica dell'utente: non entra nella cronologia e **ri-fissa l'istantanea di
1556
+ * riferimento**, cosi' aprire un documento non produce «modificata». Un indicatore che dice
1557
+ * «modificata» appena si apre insegna a ignorarlo, e un indicatore ignorato e' peggio di
1558
+ * nessun indicatore. Il prezzo accettato: chi chiude senza salvare perde le coordinate
1559
+ * calcolate, che dagre rigenera in modo deterministico.
1560
+ *
1561
+ * Il riferimento si sposta **solo** se il documento non era gia' modificato: se l'utente ha
1562
+ * scritto qualcosa, un layout non puo' dichiarare salvato il suo lavoro.
1563
+ */
1564
+ applyInitialPositions(positions: ReadonlyMap<string, DpeNodePosition>): void;
1565
+ /**
1566
+ * Collega una porta di ingresso di `targetNodeName` al nodo `sourceName`. Non verifica che
1567
+ * il collegamento sia lecito: cicli (**I2**) e riferimenti a valle (**I3**) li rifiuta il
1568
+ * backend, e l'errore compare subito perche' la validazione parte dopo la mutazione.
1569
+ */
1570
+ connect(targetNodeName: string, slot: string, sourceName: string, index?: number): void;
1571
+ /** Scollega una porta: lo slot torna vuoto, non a stringa vuota. */
1572
+ disconnect(targetNodeName: string, slot: string, index?: number): void;
1573
+ undo(): void;
1574
+ redo(): void;
1575
+ private writeReference;
1576
+ /** Scrive le posizioni su tutte le collezioni producendo una nuova definizione. */
1577
+ private withPositions;
1578
+ /**
1579
+ * Sostituisce una collezione producendo una nuova definizione. Il cast e' confinato qui:
1580
+ * TypeScript non correla la chiave di collezione con il tipo di nodo dentro un accesso
1581
+ * dinamico, e la mappa dei tipi serve ai chiamanti, non a questa riga.
1582
+ */
1583
+ private withCollection;
1584
+ private commit;
1585
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeDocumentStore, never>;
1586
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<DpeDocumentStore>;
1587
+ }
1588
+
1589
+ interface DpeLayoutNodeInput {
1590
+ name: string;
1591
+ width: number;
1592
+ height: number;
1593
+ }
1594
+ interface DpeLayoutEdgeInput {
1595
+ /** Nome del nodo a monte. */
1596
+ from: string;
1597
+ /** Nome del nodo a valle. */
1598
+ to: string;
1599
+ /** Identificatore dell'arco: dagre ne ha bisogno per ammettere archi paralleli. */
1600
+ id: string;
1601
+ }
1602
+ interface DpeLayoutPosition {
1603
+ x: number;
1604
+ y: number;
1605
+ }
1606
+ type DpeLayoutDirection = 'TB' | 'LR';
1607
+ interface DpeLayoutOptions {
1608
+ /** Default `TB`: i dati scendono dalle sorgenti ai sink. */
1609
+ direction?: DpeLayoutDirection;
1610
+ /** Distanza fra i livelli. */
1611
+ rankSeparation?: number;
1612
+ /** Distanza fra i nodi dello stesso livello. */
1613
+ nodeSeparation?: number;
1614
+ /** Angolo in alto a sinistra del grafo risultante. */
1615
+ origin?: DpeLayoutPosition;
1616
+ }
1617
+ declare class DpeLayoutService {
1618
+ /**
1619
+ * Calcola le posizioni. La chiave della mappa e' il **nome** del nodo, non il suo id sul
1620
+ * canvas: il nome e' cio' che identifica un nodo nel documento, e passare dall'id
1621
+ * costringerebbe questo servizio a conoscere la costruzione degli id.
1622
+ */
1623
+ layout(nodes: readonly DpeLayoutNodeInput[], edges: readonly DpeLayoutEdgeInput[], options?: DpeLayoutOptions): Map<string, DpeLayoutPosition>;
1624
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeLayoutService, never>;
1625
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<DpeLayoutService>;
1626
+ }
1627
+
1628
+ interface DpeTableState {
1629
+ outcome: TableLookupOutcome;
1630
+ table?: TableDescriptor;
1631
+ }
1632
+ declare class DpeMetadataStore {
1633
+ private readonly api;
1634
+ private readonly _tables;
1635
+ private readonly _isLoadingTables;
1636
+ private readonly _tablesRequested;
1637
+ private readonly _byName;
1638
+ private readonly pending;
1639
+ readonly tables: _angular_core.Signal<readonly TableSummary[]>;
1640
+ readonly isLoadingTables: _angular_core.Signal<boolean>;
1641
+ /** Idempotente: la prima chiamata carica, le successive non fanno nulla. */
1642
+ loadTables(): void;
1643
+ /** Stato noto di una tabella, se già richiesta. */
1644
+ stateOf(tableName: string): DpeTableState | undefined;
1645
+ /** Chiede la descrizione di una tabella una sola volta per nome. */
1646
+ describe(tableName: string): void;
1647
+ private put;
1648
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeMetadataStore, never>;
1649
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<DpeMetadataStore>;
1650
+ }
1651
+
1652
+ /**
1653
+ * Catalogo delle categorie di nodo: etichetta italiana, collezione JSON di appartenenza,
1654
+ * numero di sorgenti ammesse.
1655
+ *
1656
+ * **Descrittivo, non normativo.** Serve alla palette e alle etichette dell'interfaccia. Non
1657
+ * e' validazione: che un `AppendNode` con una sola sorgente sia sbagliato lo dice il backend,
1658
+ * non questo file, e i due non devono mai diventare due fonti di verita' in disaccordo. I
1659
+ * conteggi qui sotto servono a decidere **quante porte disegnare**, che e' una domanda di
1660
+ * rendering.
1661
+ */
1662
+
1663
+ interface DpeNodeCategory {
1664
+ /** Collezione JSON della radice: e' anche la chiave con cui si legge il documento. */
1665
+ collection: DpeNodeCollectionName;
1666
+ /** Etichetta breve, per la palette e per l'intestazione della card sul canvas. */
1667
+ label: string;
1668
+ /** Una riga di spiegazione, per il tooltip della palette. */
1669
+ description: string;
1670
+ /** Numero minimo di sorgenti che il nodo dichiara (0 per i punti d'ingresso). */
1671
+ minSources: number;
1672
+ /** Numero massimo, `undefined` = illimitato (`Append`, `CustomNode`). */
1673
+ maxSources?: number;
1674
+ /** Vero per i punti d'ingresso del grafo. */
1675
+ isSource: boolean;
1676
+ /** Vero per i sink: producono l'artefatto, non uno schema. */
1677
+ isSink: boolean;
1678
+ /**
1679
+ * Vero dove il backend rifiuta la compilazione pur accettando il modello (**I10**): la UI
1680
+ * deve poter avvisare **prima** che l'utente costruisca la pipeline intorno a un nodo che
1681
+ * non arrivera' all'SQL. Non e' una regola di dominio riprodotta: e' l'informazione che
1682
+ * `docs/domain-model.md` dichiara esplicitamente per queste due categorie, e la
1683
+ * diagnostica autorevole resta `DPE_NODE_NOT_COMPILABLE` del backend.
1684
+ */
1685
+ isNotCompilableInV1: boolean;
1686
+ }
1687
+ declare const DPE_NODE_CATEGORIES: readonly DpeNodeCategory[];
1688
+ declare function dpeNodeCategory(collection: DpeNodeCollectionName): DpeNodeCategory;
1689
+ /** Nomi dei dialetti per il selettore. La libreria conosce **solo** il nome (ADR 0009). */
1690
+ declare const DPE_DIALECT_LABELS: Readonly<Record<string, string>>;
1691
+
1692
+ /**
1693
+ * I tracciati SVG delle icone di categoria, uno per collezione di nodi.
1694
+ *
1695
+ * **Perche' tracciati e non glifi Unicode** (divergenza motivata dal progetto di riferimento,
1696
+ * `frontend.md` §3-ter): i glifi non hanno metriche ne' linea di base coerenti fra loro e su
1697
+ * alcune piattaforme diventano emoji a colori — cioe' proprio la resa sbagliata quando stanno
1698
+ * in colonna in una palette. Un tracciato disegnato su una griglia 24x24 con `currentColor` si
1699
+ * colora con una sola regola CSS e vale identico in tema chiaro e scuro.
1700
+ *
1701
+ * **Nessun asset e nessuna dipendenza**: sono stringhe, e il componente che le rende le lega con
1702
+ * `[attr.d]` senza mai toccare `innerHTML` — quindi niente `bypassSecurityTrust*`.
1703
+ *
1704
+ * Il disegno e' pensato per la resa a **16px**: pochi tratti, nessun dettaglio sotto i 2 px di
1705
+ * griglia, e sagome che restano distinguibili l'una dall'altra quando sono incolonnate.
1706
+ */
1707
+
1708
+ /**
1709
+ * La famiglia cromatica di una categoria. **Non e' una tassonomia nuova**: si deriva per intero
1710
+ * da `isSource`/`isSink`/`isNotCompilableInV1` del catalogo, che restano l'unica descrizione dei
1711
+ * tipi di nodo. Serve solo a scegliere un colore.
1712
+ */
1713
+ type DpeNodeIconFamily = 'source' | 'transform' | 'sink' | 'uncompilable';
1714
+ declare function dpeNodeIconFamily(collection: DpeNodeCollectionName): DpeNodeIconFamily;
1715
+ /** Classe CSS della famiglia: un solo posto la costruisce, cosi' i fogli restano allineati. */
1716
+ declare function dpeNodeIconFamilyClass(collection: DpeNodeCollectionName): string;
1717
+ /**
1718
+ * I tracciati, per collezione. Ogni voce e' l'elenco degli attributi `d` di un `<path>`; il
1719
+ * contorno e' `stroke`, mai `fill`, cosi' l'icona pesa uguale su qualunque sfondo.
1720
+ */
1721
+ declare const DPE_NODE_ICON_PATHS: Readonly<Record<DpeNodeCollectionName, readonly string[]>>;
1722
+ /**
1723
+ * I tracciati di una collezione. Il ripiego vuoto non e' pigrizia: una collezione aggiunta al
1724
+ * modello e non ancora disegnata deve produrre una pastiglia vuota, non un errore in console
1725
+ * ne' un `undefined` dentro `[attr.d]`.
1726
+ */
1727
+ declare function dpeNodeIconPaths(collection: DpeNodeCollectionName): readonly string[];
1728
+
1729
+ /**
1730
+ * Creazione di un nodo nuovo: nome candidato e valori iniziali per categoria.
1731
+ *
1732
+ * Non e' validazione e non e' dominio. Serve a una cosa sola: un nodo appena rilasciato sul
1733
+ * canvas deve essere **rappresentabile** e distinguibile, cioe' avere un nome e un'etichetta.
1734
+ * Tutto il resto lo compila l'utente nell'ispettore, e cosa sia obbligatorio lo dice il
1735
+ * backend.
1736
+ *
1737
+ * Il nome candidato e' unico rispetto ai nomi già presenti con confronto **esatto**
1738
+ * (`contracts.md` §2: unicita' verificata `OrdinalIgnoreCase`, risoluzione `Ordinal`). Qui il
1739
+ * confronto e' insensibile al caso di proposito: proporre `Filtro2` accanto a un `filtro2`
1740
+ * esistente creerebbe un `DPE_MODEL_NAME_DUPLICATE` a nome dell'editor, non dell'utente.
1741
+ */
1742
+
1743
+ /** Il primo nome libero della forma `<radice><n>`. */
1744
+ declare function dpeProposeNodeName(definition: DpeDefinition, collection: DpeNodeCollectionName): string;
1745
+ /**
1746
+ * Il nodo iniziale di una categoria. I campi obbligatori senza un valore sensato restano
1747
+ * **assenti**, non riempiti con un segnaposto: un `tableName` finto passerebbe la forma e
1748
+ * fallirebbe sul provider di metadati con un errore che l'utente non ha causato.
1749
+ */
1750
+ declare function dpeCreateNode<K extends DpeNodeCollectionName>(definition: DpeDefinition, collection: K): DpeNodeCollectionMap[K];
1751
+ /**
1752
+ * La sequenza dei sink e' univoca fra writeback e gruppi atomici: si propone la prima libera.
1753
+ * L'unicita' la verifica il backend (`DPE_WRITEBACK_SEQUENCE_DUPLICATE`) — questo e' solo un
1754
+ * valore iniziale che non collide, non un controllo.
1755
+ */
1756
+ declare function dpeProposeWritebackSequence(definition: DpeDefinition): number;
1757
+ /** Etichetta di sintesi mostrata sulla card del nodo, sotto il nome. */
1758
+ declare function dpeNodeSubtitle(collection: DpeNodeCollectionName, node: DpeAnyNode): string | null;
1759
+
1760
+ declare class DpeValidationService {
1761
+ private readonly api;
1762
+ private readonly store;
1763
+ private readonly destroyRef;
1764
+ private readonly _isValidating;
1765
+ private readonly _isCompiling;
1766
+ private readonly _error;
1767
+ /**
1768
+ * Le primitive opzionali si sanno **alla costruzione**, per identita' del metodo
1769
+ * (`dpe-capabilities.ts`, `contracts.md` §7). Prima si partiva da «disponibile» e si scopriva
1770
+ * l'assenza dal primo `MissingService`: il comando sembrava attivo e falliva alla pressione,
1771
+ * che e' peggio di un comando disabilitato che ne dice il motivo.
1772
+ */
1773
+ private readonly capabilities;
1774
+ private readonly _isPreviewAvailable;
1775
+ private readonly _isSaving;
1776
+ /** Come l'anteprima: un host senza `save` disabilita il comando, non rompe l'editor. */
1777
+ private readonly _isSaveAvailable;
1778
+ /** Esito dell'ultimo salvataggio: transitorio al successo, persistente al fallimento. */
1779
+ private readonly _justSaved;
1780
+ private readonly _saveError;
1781
+ /**
1782
+ * Il dialetto **dichiarato dall'ambiente** (ADR 0017), quando l'host espone `getEnvironment`.
1783
+ * Non e' il dialetto con cui si compila — quello sta nella definizione — ed e' esattamente per
1784
+ * questo che i due si tengono separati: il confronto e' l'unica cosa che l'editor puo' dire.
1785
+ */
1786
+ private readonly _environmentDialect;
1787
+ readonly isValidating: _angular_core.Signal<boolean>;
1788
+ readonly isCompiling: _angular_core.Signal<boolean>;
1789
+ readonly error: _angular_core.Signal<DpeApiError | undefined>;
1790
+ readonly isPreviewAvailable: _angular_core.Signal<boolean>;
1791
+ readonly isSaving: _angular_core.Signal<boolean>;
1792
+ readonly isSaveAvailable: _angular_core.Signal<boolean>;
1793
+ readonly justSaved: _angular_core.Signal<boolean>;
1794
+ readonly saveError: _angular_core.Signal<DpeApiError | undefined>;
1795
+ readonly environmentDialect: _angular_core.Signal<SqlDialectKind | undefined>;
1796
+ /** Vero finche' non e' arrivata la prima risposta: la UI non deve dire "nessun problema". */
1797
+ readonly hasResult: _angular_core.Signal<boolean>;
1798
+ constructor();
1799
+ /** Anteprima dell'SQL. Opzionale sull'host: assente, il comando resta disabilitato. */
1800
+ requestPreview(parameterValues?: DpeParameterValue[]): void;
1801
+ /**
1802
+ * Salvataggio attraverso `DpeBuilderApi.save` (opzionale, `contracts.md` §7). Al successo
1803
+ * **l'editor dichiara da se'** lo stato salvato: quando l'ospite espone il metodo, e' questo il
1804
+ * punto che sa se e' andato a buon fine.
1805
+ *
1806
+ * Si passa a `markSaved` **il documento inviato**, non quello corrente: se l'utente scrive
1807
+ * mentre il salvataggio e' in volo, quelle modifiche non sono state salvate e l'indicatore deve
1808
+ * continuare a dirlo.
1809
+ */
1810
+ save(): void;
1811
+ dismissError(): void;
1812
+ dismissSaveError(): void;
1813
+ private saveNoticeTimer;
1814
+ private showSaveNotice;
1815
+ private clearSaveNotice;
1816
+ /**
1817
+ * Un host che non usa `DpeApiError` non deve far esplodere l'editor: cio' che non e'
1818
+ * categorizzato diventa `Transport`, che e' la categoria "riprovabile".
1819
+ */
1820
+ private toApiError;
1821
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeValidationService, never>;
1822
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<DpeValidationService>;
1823
+ }
1824
+
1825
+ /**
1826
+ * Geometria della viewport: funzioni pure, nessun DOM.
1827
+ *
1828
+ * Serve a una sola domanda, che si pone quando si naviga da una diagnostica al nodo: **il nodo
1829
+ * e' interamente in vista?** Se lo e', non si sposta niente — una panoramica non richiesta
1830
+ * disorienta quanto la sua assenza. Se non lo e', si centra la **vista**, non il nodo: le
1831
+ * coordinate del documento non si toccano.
1832
+ *
1833
+ * Sta qui e non nel componente perche' e' esattamente il tipo di logica che si sbaglia in
1834
+ * silenzio (un `>` al posto di un `>=`, un margine dimenticato) e che si verifica senza browser.
1835
+ */
1836
+ /** Rettangolo in coordinate di schermo, la forma che `getBoundingClientRect` restituisce. */
1837
+ interface DpeRect {
1838
+ left: number;
1839
+ top: number;
1840
+ right: number;
1841
+ bottom: number;
1842
+ }
1843
+ /**
1844
+ * Vero quando `target` sta **interamente** dentro `view`, lasciando `margin` pixel di respiro su
1845
+ * ogni lato. Il margine non e' un vezzo: un nodo tangente al bordo e' tecnicamente visibile e
1846
+ * praticamente illeggibile, e senza respiro il criterio "e' visibile" scatterebbe anche quando
1847
+ * dell'ombra e del connettore di uscita non si vede nulla.
1848
+ */
1849
+ declare function dpeIsRectFullyVisible(target: DpeRect, view: DpeRect, margin?: number): boolean;
1850
+
1851
+ /** Le tre viste in basso: una alla volta, perche' guardano la stessa cosa da tre angoli. */
1852
+ type DpeBottomTab = 'diagnostics' | 'schema' | 'sql';
1853
+ declare class DpeBuilderComponent {
1854
+ protected readonly store: DpeDocumentStore;
1855
+ protected readonly validation: DpeValidationService;
1856
+ private readonly layout;
1857
+ /** La definizione da editare. Cambiarne l'identita' ricarica il documento. */
1858
+ readonly definition: _angular_core.InputSignal<DpeDefinition>;
1859
+ readonly isEditable: _angular_core.InputSignal<boolean>;
1860
+ /**
1861
+ * Emessa a ogni mutazione. L'ospite **non deve** rimandarla dentro `definition`: sarebbe un
1862
+ * ciclo, e ricaricare azzera la cronologia. Serve per salvare, non per pilotare l'editor.
1863
+ */
1864
+ readonly definitionChange: _angular_core.OutputEmitterRef<DpeDefinition>;
1865
+ protected readonly dialectLabels: Readonly<Record<string, string>>;
1866
+ protected readonly bottomTab: _angular_core.WritableSignal<DpeBottomTab>;
1867
+ private readonly canvas;
1868
+ /**
1869
+ * Il dialetto **della definizione**: e' quello con cui il backend compilera' (ADR 0009), quindi
1870
+ * e' quello che il badge mostra. In sola lettura: nessun comando dell'interfaccia lo cambia
1871
+ * (ADR 0017), perche' il database di destinazione e' un fatto dell'ambiente e non una
1872
+ * preferenza dell'autore.
1873
+ */
1874
+ protected readonly dialect: Signal<SqlDialectKind>;
1875
+ /**
1876
+ * Disallineamento fra cio' che l'ambiente dichiara e cio' che la definizione porta. Si
1877
+ * **segnala** e non si corregge: correggere vorrebbe dire migrare le espressioni SQL native
1878
+ * (ADR 0006), che e' dell'host. Assente `getEnvironment`, non c'e' niente da confrontare.
1879
+ */
1880
+ protected readonly dialectMismatch: Signal<SqlDialectKind | undefined>;
1881
+ protected readonly canSave: Signal<boolean>;
1882
+ protected readonly nodeCount: Signal<number>;
1883
+ constructor();
1884
+ /** Comando «Riordina»: e' un'azione dell'utente, quindi annullabile e "modifica". */
1885
+ protected runAutoLayout(): void;
1886
+ /**
1887
+ * `isInitial` distingue due cose che dagre calcola allo stesso modo e che l'editor deve trattare
1888
+ * in modo opposto: disporre un documento che **non porta** coordinate non e' una modifica
1889
+ * dell'utente; riordinare su richiesta lo e'.
1890
+ */
1891
+ private runLayout;
1892
+ protected onNodeDropped(event: {
1893
+ collection: DpeNodeCollectionName;
1894
+ x: number;
1895
+ y: number;
1896
+ }): void;
1897
+ /** Clic sulla palette (via tastiera compresa): il nodo nasce in un punto libero e prevedibile. */
1898
+ protected onNodeRequested(collection: DpeNodeCollectionName): void;
1899
+ /**
1900
+ * `Ctrl+S` (e `Cmd+S`): stesse condizioni di abilitazione del bottone. `preventDefault` sempre
1901
+ * che la scorciatoia sia nostra, anche quando il salvataggio non e' possibile: lasciare passare
1902
+ * il «salva pagina» del browser proprio dentro un editor sarebbe la risposta sbagliata a un
1903
+ * gesto giusto.
1904
+ */
1905
+ protected onKeyDown(event: KeyboardEvent): void;
1906
+ /**
1907
+ * Navigazione da una diagnostica: **selezione e vista**. Il `DiagnosticPath` promette di portare
1908
+ * sul nodo e sul campo; selezionare senza inquadrare mantiene meta' della promessa, e il nodo
1909
+ * resta fuori schermo mentre l'ispettore parla di lui.
1910
+ */
1911
+ protected onNavigate(event: {
1912
+ nodeName: string;
1913
+ }): void;
1914
+ /**
1915
+ * Stato **sporco** del documento, per l'ospite che deve decidere se lasciar navigare via
1916
+ * (ADR 0019). Delega a `DpeDocumentStore.isDirty`.
1917
+ *
1918
+ * Si legge tramite `viewChild` **quando serve**, non si rispecchia in uno stato dell'ospite: un
1919
+ * mirror di stato sporco che va fuori sincrono e' peggio del problema che risolve. La conferma
1920
+ * prima di abbandonare le modifiche e' dell'ospite, perche' e' l'ospite che naviga — la libreria
1921
+ * non sa se andare via significhi cambiare schermata, scheda o applicazione.
1922
+ */
1923
+ readonly isDirty: Signal<boolean>;
1924
+ /**
1925
+ * Da chiamare dopo un salvataggio riuscito: da quel momento il documento risulta "senza
1926
+ * modifiche". Lo decide l'ospite, perche' solo lui sa se il salvataggio e' andato a buon fine.
1927
+ */
1928
+ markSaved(): void;
1929
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeBuilderComponent, never>;
1930
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeBuilderComponent, "dpe-builder", never, { "definition": { "alias": "definition"; "required": true; "isSignal": true; }; "isEditable": { "alias": "isEditable"; "required": false; "isSignal": true; }; }, { "definitionChange": "definitionChange"; }, never, never, true, never>;
1931
+ }
1932
+
1933
+ /**
1934
+ * View model del canvas.
1935
+ *
1936
+ * Gli **id** non si costruiscono qui: vengono da `core/dpe-graph.ts`, che e' l'unico posto che
1937
+ * li conosce. Qui stanno solo le misure, e stanno qui perche' servono a due consumatori che
1938
+ * devono concordare: il CSS che disegna la card e dagre che calcola il layout. Se divergono,
1939
+ * il layout automatico lascia i nodi sovrapposti.
1940
+ */
1941
+
1942
+ /** Altezza nominale della card: non cambia con il numero di porte, che stanno in fila sopra. */
1943
+ declare const DPE_NODE_HEIGHT = 104;
1944
+ declare function dpeNodeWidth(portCount: number): number;
1945
+ declare function dpeNodeWidthClass(portCount: number): string;
1946
+ interface DpeCanvasPort {
1947
+ id: string;
1948
+ slot: string;
1949
+ index?: number;
1950
+ /** Etichetta della porta: si mostra solo dove le porte sono piu' di una. */
1951
+ label: string;
1952
+ /** Nome collegato, assente se la porta e' libera. */
1953
+ sourceName?: string;
1954
+ /** Il nome collegato non corrisponde a nessun nodo: si dice sulla porta. */
1955
+ isBroken: boolean;
1956
+ }
1957
+ interface DpeCanvasNode {
1958
+ /** Nome nel documento: l'identita', anche per la selezione. */
1959
+ name: string;
1960
+ /** Id per il canvas, costruito da `dpeNodeId`. */
1961
+ id: string;
1962
+ collection: DpeNodeCollectionName;
1963
+ categoryLabel: string;
1964
+ label: string;
1965
+ subtitle: string | null;
1966
+ position: {
1967
+ x: number;
1968
+ y: number;
1969
+ };
1970
+ ports: DpeCanvasPort[];
1971
+ showsPortLabels: boolean;
1972
+ widthClass: string;
1973
+ /**
1974
+ * Classe della famiglia cromatica (`dpe-cat--*`): la calcola `core/dpe-node-icons.ts` dai
1975
+ * flag del catalogo. Sta nel view model e non nel template perche' e' la stessa che usa la
1976
+ * palette, e due modi di derivarla sarebbero due colori diversi per lo stesso tipo di nodo.
1977
+ */
1978
+ familyClass: string;
1979
+ outputPortId: string;
1980
+ /** I sink non producono uno schema: la porta di uscita non si disegna... */
1981
+ hasOutput: boolean;
1982
+ /** Gravita' peggiore fra le diagnostiche del nodo. */
1983
+ severity: DiagnosticSeverity | null;
1984
+ diagnosticCount: number;
1985
+ /**
1986
+ * Nodo **valido ma non compilabile** (**I10**): stato distinto da "non valido", con un
1987
+ * colore proprio. Sono due situazioni diverse e l'utente deve capire subito quale guarda.
1988
+ */
1989
+ isNotCompilable: boolean;
1990
+ /** Numero di colonne dello schema di uscita, quando il backend lo ha detto. */
1991
+ columnCount: number | null;
1992
+ }
1993
+ interface DpeCanvasEdge {
1994
+ id: string;
1995
+ sourceId: string;
1996
+ targetId: string;
1997
+ slot: string;
1998
+ }
1999
+
2000
+ declare class DpeCanvasComponent {
2001
+ private readonly store;
2002
+ /** Serve per misurare l'area disponibile prima di decidere la scala d'apertura. */
2003
+ private readonly host;
2004
+ /** Marker "all states": senza, l'arco selezionato perde la punta. */
2005
+ readonly markerEnd = EFMarkerType.END_ALL_STATES;
2006
+ /**
2007
+ * Ingressi in alto, uscita in basso, **dichiarati**. Lasciando calcolare il lato, un arco
2008
+ * che risale (un nodo posizionato sopra la sua sorgente) esce di fianco e il grafo diventa
2009
+ * illeggibile.
2010
+ */
2011
+ readonly sides: typeof EFConnectableSide;
2012
+ readonly isEditable: _angular_core.InputSignal<boolean>;
2013
+ readonly nodeOpened: _angular_core.OutputEmitterRef<string>;
2014
+ readonly nodeDropped: _angular_core.OutputEmitterRef<{
2015
+ collection: DpeNodeCollectionName;
2016
+ x: number;
2017
+ y: number;
2018
+ }>;
2019
+ private readonly canvas;
2020
+ /**
2021
+ * Serve solo a **riallineare** la selezione della libreria a quella dello store: e' l'unico
2022
+ * punto che scrive nello stato di selezione di @foblex/flow.
2023
+ */
2024
+ private readonly flow;
2025
+ private hasFramedOnce;
2026
+ /**
2027
+ * Visibilita' del comando «Inquadra». Non e' piu' «l'utente ha spostato la vista»: lo diventa
2028
+ * anche all'apertura quando l'editor rinuncia a inquadrare per non scendere sotto
2029
+ * `MIN_INITIAL_SCALE`. In quel caso la vista d'insieme non e' stata data, quindi il comando che
2030
+ * la offre deve essere raggiungibile — nasconderlo significherebbe toglierla e basta.
2031
+ */
2032
+ private readonly _isFitCommandVisible;
2033
+ readonly isFitCommandVisible: _angular_core.Signal<boolean>;
2034
+ readonly nodes: _angular_core.Signal<DpeCanvasNode[]>;
2035
+ /**
2036
+ * Solo gli archi con **entrambi** i capi risolti diventano `<f-connection>`: un capo che non
2037
+ * esiste non ha un connettore, e una connessione verso un id inesistente si attacca a un
2038
+ * punto arbitrario del canvas. Il riferimento rotto si vede sulla porta del nodo.
2039
+ */
2040
+ readonly edges: _angular_core.Signal<DpeCanvasEdge[]>;
2041
+ constructor();
2042
+ /**
2043
+ * Porta il nodo in vista **muovendo la vista**, non il nodo: le coordinate del documento non si
2044
+ * toccano (una navigazione non e' una modifica). Se il nodo e' gia' interamente visibile non fa
2045
+ * nulla, perche' una panoramica non richiesta disorienta quanto la sua assenza.
2046
+ */
2047
+ revealNode(name: string): void;
2048
+ /**
2049
+ * Il nodo nel DOM. Si scorre l'elenco invece di comporre un selettore con il valore
2050
+ * dell'attributo: il nome del nodo arriva dal documento e puo' contenere qualunque carattere,
2051
+ * e un selettore costruito per concatenazione su un dato del documento e' un errore in attesa.
2052
+ */
2053
+ private findNodeElement;
2054
+ /** Misure per il layout automatico: le stesse che il CSS applica con le classi. */
2055
+ layoutInput(): {
2056
+ name: string;
2057
+ width: number;
2058
+ height: number;
2059
+ }[];
2060
+ /**
2061
+ * `fitToScreen` va chiamato **dopo** il render dei nodi: prima, la libreria non conosce
2062
+ * ancora le loro dimensioni e inquadra la vista sbagliata. Solo la prima volta: rifarlo
2063
+ * combatterebbe con l'utente che ha spostato la vista.
2064
+ */
2065
+ onNodesRendered(): void;
2066
+ /** Vero quando inquadrare tutto il grafo richiederebbe una scala sotto la soglia leggibile. */
2067
+ private wouldFitBelowMinimumScale;
2068
+ onCanvasChange(): void;
2069
+ resetViewport(): void;
2070
+ /**
2071
+ * Creazione di un arco: si scrive il **riferimento** sulla porta di destinazione. La
2072
+ * direzione del gesto e' irrilevante — cio' che conta e' quale slot riceve il nome, ed e'
2073
+ * per questo che le porte di ingresso sono una per slot.
2074
+ */
2075
+ onCreateConnection(event: {
2076
+ sourceId: string;
2077
+ targetId?: string;
2078
+ }): void;
2079
+ /** Riassegnazione di un arco già disegnato, da un capo o dall'altro. */
2080
+ onReassignConnection(event: {
2081
+ endpoint: string;
2082
+ previousSourceId: string;
2083
+ nextSourceId?: string;
2084
+ previousTargetId: string;
2085
+ nextTargetId?: string;
2086
+ }): void;
2087
+ /**
2088
+ * Spostamento: un solo passo di cronologia per l'intero gesto. Le posizioni intermedie non
2089
+ * sono modifiche che l'utente vuole annullare una per una.
2090
+ */
2091
+ onMoveNodes(event: {
2092
+ nodes: Array<{
2093
+ id: string;
2094
+ position: {
2095
+ x: number;
2096
+ y: number;
2097
+ };
2098
+ }>;
2099
+ }): void;
2100
+ /**
2101
+ * Il gesto di selezione della libreria entra **nello store** e non altrove: e' l'unico verso in
2102
+ * cui la selezione di @foblex/flow conta, come rilevazione del gesto. Cio' che si vede lo decide
2103
+ * lo store, attraverso l'effect del costruttore.
2104
+ */
2105
+ onSelectionChange(event: {
2106
+ nodeIds: string[];
2107
+ }): void;
2108
+ onDeleteSelected(event: {
2109
+ nodeIds: string[];
2110
+ }): void;
2111
+ /**
2112
+ * Rilascio di una voce trascinata dalla palette. `externalItemRect` e' già nel sistema di
2113
+ * coordinate del canvas: convertirlo a mano dal viewport sarebbe rifare la trasformazione
2114
+ * di zoom e panoramica della libreria.
2115
+ */
2116
+ onCreateNode(event: {
2117
+ data: unknown;
2118
+ externalItemRect: {
2119
+ x: number;
2120
+ y: number;
2121
+ };
2122
+ }): void;
2123
+ onNodeDoubleClick(name: string): void;
2124
+ onEditClick(event: Event, name: string): void;
2125
+ onRemoveClick(event: Event, name: string): void;
2126
+ /** La classe nel DOM **deriva** dallo store: non e' una seconda registrazione della selezione. */
2127
+ isSelected(node: DpeCanvasNode): boolean;
2128
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeCanvasComponent, never>;
2129
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeCanvasComponent, "dpe-canvas", never, { "isEditable": { "alias": "isEditable"; "required": false; "isSignal": true; }; }, { "nodeOpened": "nodeOpened"; "nodeDropped": "nodeDropped"; }, never, never, true, never>;
2130
+ }
2131
+
2132
+ declare class DpeCatalogComponent {
2133
+ protected readonly store: DpeCatalogStore;
2134
+ private readonly injector;
2135
+ /**
2136
+ * Il **nome** della definizione da aprire. Non la definizione: caricarla e' dell'ospite, che
2137
+ * potrebbe volerlo fare per vie proprie.
2138
+ */
2139
+ readonly open: _angular_core.OutputEmitterRef<string>;
2140
+ protected readonly dialectLabels: Readonly<Record<string, string>>;
2141
+ /** Filtro **locale** sui sommari gia' ricevuti: non e' una query al backend (ADR 0019). */
2142
+ protected readonly filter: _angular_core.WritableSignal<string>;
2143
+ protected readonly newName: _angular_core.WritableSignal<string>;
2144
+ protected readonly newLabel: _angular_core.WritableSignal<string>;
2145
+ /**
2146
+ * Conferma in **due passi**: un elenco in cui un clic distratto cancella non e' un elenco.
2147
+ * Tiene il nome invece di un booleano perche' la conferma appartiene a **quella** riga.
2148
+ */
2149
+ protected readonly pendingDelete: _angular_core.WritableSignal<string | null>;
2150
+ /** Riga in duplicazione, con i due campi del nome e dell'etichetta nuovi. */
2151
+ protected readonly duplicateSource: _angular_core.WritableSignal<string | null>;
2152
+ protected readonly duplicateName: _angular_core.WritableSignal<string>;
2153
+ protected readonly duplicateLabel: _angular_core.WritableSignal<string>;
2154
+ private readonly duplicateNameField;
2155
+ /**
2156
+ * Il filtro non tocca l'ordine: si tolgono righe, non si riordinano. `toLocaleLowerCase` e non
2157
+ * `toLowerCase` perche' un elenco di definizioni italiane si filtra anche per lettere accentate.
2158
+ */
2159
+ protected readonly visible: _angular_core.Signal<readonly DpeDefinitionSummary[]>;
2160
+ /** Vero quando il filtro ha nascosto tutto: e' un messaggio diverso da «nessuna definizione». */
2161
+ protected readonly isFilteredEmpty: _angular_core.Signal<boolean>;
2162
+ /**
2163
+ * Duplicare richiede **due** primitive, `load` e `createDefinition`: non esiste una primitiva
2164
+ * di duplicazione, il comando si compone da queste.
2165
+ */
2166
+ protected readonly canDuplicate: _angular_core.Signal<boolean>;
2167
+ protected readonly duplicateReason: _angular_core.Signal<"Duplica: carica questa definizione e la ricrea con un nome nuovo" | "Duplicazione non disponibile: questo ambiente non implementa load e createDefinition.">;
2168
+ /** Validazione **di forma**, l'unica ammessa nel frontend: due campi non vuoti. */
2169
+ protected readonly canSubmitNew: _angular_core.Signal<boolean>;
2170
+ protected readonly canSubmitDuplicate: _angular_core.Signal<boolean>;
2171
+ protected onOpen(name: string): void;
2172
+ protected refresh(): void;
2173
+ /**
2174
+ * Crea e **apre il nome tornato dall'ospite**, non quello digitato: l'ospite puo' averlo
2175
+ * normalizzato, e aprire quello digitato aprirebbe una definizione che non esiste.
2176
+ */
2177
+ protected createNew(): void;
2178
+ protected startDuplicate(summary: DpeDefinitionSummary): void;
2179
+ protected cancelDuplicate(): void;
2180
+ protected confirmDuplicate(): void;
2181
+ protected askDelete(name: string): void;
2182
+ protected cancelDelete(): void;
2183
+ protected confirmDelete(name: string): void;
2184
+ /** Solo la data, senza ora: un elenco non e' un registro di audit. */
2185
+ protected formatDate(value: string): string;
2186
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeCatalogComponent, never>;
2187
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeCatalogComponent, "dpe-catalog", never, {}, { "open": "open"; }, never, never, true, never>;
2188
+ }
2189
+
2190
+ /** Un gruppo dell'elenco: intestazione e voci. Presentazione, non semantica. */
2191
+ interface DpeNodePaletteGroup {
2192
+ key: 'sources' | 'transforms' | 'sinks';
2193
+ label: string;
2194
+ categories: readonly DpeNodeCategory[];
2195
+ }
2196
+ declare class DpeNodePaletteComponent {
2197
+ /** Clic sulla voce: il nodo si crea al centro dell'area, non dove stava il puntatore. */
2198
+ readonly nodeRequested: _angular_core.OutputEmitterRef<keyof _esfaenza_dpe_builder.DpeNodeCollectionMap>;
2199
+ protected readonly filter: _angular_core.WritableSignal<string>;
2200
+ readonly visible: _angular_core.Signal<readonly DpeNodeCategory[]>;
2201
+ /**
2202
+ * Tre gruppi, nell'ordine in cui si costruisce una pipeline: da dove entrano i dati, cosa ci
2203
+ * si fa, dove finiscono. I gruppi vuoti non compaiono, altrimenti una ricerca lascerebbe sullo
2204
+ * schermo intestazioni senza voci.
2205
+ */
2206
+ readonly groups: _angular_core.Signal<readonly DpeNodePaletteGroup[]>;
2207
+ protected familyClass(category: DpeNodeCategory): string;
2208
+ /** Il testo che la descrizione non mostra piu' nel corpo della voce. */
2209
+ protected titleOf(category: DpeNodeCategory): string;
2210
+ protected text(event: Event): string;
2211
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeNodePaletteComponent, never>;
2212
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeNodePaletteComponent, "dpe-node-palette", never, {}, { "nodeRequested": "nodeRequested"; }, never, never, true, never>;
2213
+ }
2214
+
2215
+ declare class DpeNodeInspectorComponent {
2216
+ private readonly store;
2217
+ /**
2218
+ * Il riordino richiede le misure delle card, che le conosce il canvas: l'ispettore **chiede**,
2219
+ * non calcola. Componente stupido, orchestrazione fuori.
2220
+ */
2221
+ readonly layoutRequested: _angular_core.OutputEmitterRef<void>;
2222
+ readonly selectedNames: _angular_core.Signal<readonly string[]>;
2223
+ readonly located: _angular_core.Signal<_esfaenza_dpe_builder.DpeLocatedNode<keyof _esfaenza_dpe_builder.DpeNodeCollectionMap> | undefined>;
2224
+ readonly nameDraft: _angular_core.WritableSignal<string>;
2225
+ readonly categoryLabel: _angular_core.Signal<string>;
2226
+ /** La classe di famiglia dell'icona: la stessa funzione che usano palette e canvas. */
2227
+ readonly familyClass: _angular_core.Signal<string>;
2228
+ readonly columns: _angular_core.Signal<_esfaenza_dpe_builder.DpeColumnInfo[]>;
2229
+ readonly diagnostics: _angular_core.Signal<_esfaenza_dpe_builder.Diagnostic[]>;
2230
+ readonly referenceCount: _angular_core.Signal<number>;
2231
+ readonly canRename: _angular_core.Signal<boolean>;
2232
+ constructor();
2233
+ /**
2234
+ * Elimina i nodi selezionati. Si itera su una **copia** dei nomi: `removeNode` pota la selezione
2235
+ * a ogni giro, e scorrere il signal mentre lo si svuota salterebbe la meta' dei nodi.
2236
+ */
2237
+ protected removeSelected(): void;
2238
+ protected rename(currentName: string): void;
2239
+ protected setCommon(field: 'label' | 'description', value: string): void;
2240
+ protected valueOf(event: Event): string;
2241
+ protected asDataSource(node: unknown): DataSourceNode;
2242
+ protected asFilter(node: unknown): FilterNode;
2243
+ protected asJoin(node: unknown): JoinNode;
2244
+ protected asAggregate(node: unknown): AggregateNode;
2245
+ protected asTransform(node: unknown): TransformNode;
2246
+ protected asAppend(node: unknown): AppendNode;
2247
+ protected asHierarchy(node: unknown): HierarchyPathNode;
2248
+ protected asForecast(node: unknown): ForecastNode;
2249
+ protected asCustom(node: unknown): CustomNode;
2250
+ protected asWriteback(node: unknown): WritebackNode;
2251
+ protected asAtomic(node: unknown): AtomicWritebackNode;
2252
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeNodeInspectorComponent, never>;
2253
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeNodeInspectorComponent, "dpe-node-inspector", never, {}, { "layoutRequested": "layoutRequested"; }, never, never, true, never>;
2254
+ }
2255
+
2256
+ declare abstract class DpeNodeInspectorBase<TNode extends DpeAnyNode = DpeAnyNode> {
2257
+ protected readonly store: DpeDocumentStore;
2258
+ readonly nodeName: _angular_core.InputSignal<string>;
2259
+ readonly node: _angular_core.InputSignal<TNode>;
2260
+ /** La collezione di appartenenza: la sa l'ispettore, serve per scrivere nello store. */
2261
+ abstract readonly collection: DpeNodeCollectionName;
2262
+ /** Le diagnostiche ancorate a questo nodo, come le ha date il backend (**I6**). */
2263
+ readonly diagnostics: _angular_core.Signal<readonly Diagnostic[]>;
2264
+ /**
2265
+ * Il nodo e' valido ma non compilabile (**I10**): l'ispettore lo dice in testa, perche' e'
2266
+ * l'informazione che spiega perche' non compare nessun SQL — e non c'e' niente da correggere.
2267
+ */
2268
+ readonly isNotCompilable: _angular_core.Signal<boolean>;
2269
+ /** Colonne prodotte dal nodo, secondo il backend. Mai calcolate qui (**I4**). */
2270
+ readonly outputColumns: _angular_core.Signal<readonly DpeColumnInfo[]>;
2271
+ /**
2272
+ * Colonne disponibili **in ingresso**: l'unione degli schemi dei nodi a monte, nell'ordine.
2273
+ * Arrivano dal backend; se la validazione non e' ancora tornata l'elenco e' vuoto e i campi
2274
+ * si digitano a mano — che e' meglio di un elenco indovinato in locale.
2275
+ */
2276
+ readonly inputColumns: _angular_core.Signal<readonly DpeColumnInfo[]>;
2277
+ /** I parametri dichiarati sulla radice: servono a filtri e mapping dei writeback. */
2278
+ readonly parameters: _angular_core.Signal<_esfaenza_dpe_builder.DpeParameter[]>;
2279
+ /** Le diagnostiche su un campo preciso, per mostrarle **accanto** al controllo. */
2280
+ issuesOn(field: string): Diagnostic[];
2281
+ hasIssueOn(field: string): boolean;
2282
+ /** Applica una modifica al nodo. */
2283
+ protected patch(patch: Partial<TNode>): void;
2284
+ /**
2285
+ * Campo semplice: valore vuoto → chiave **rimossa**, non stringa vuota. Il backend
2286
+ * distingue assente da vuoto (`DPE_MODEL_REQUIRED_MISSING` contro un valore non valido), e
2287
+ * su Oracle la stringa vuota **e'** `NULL`: scriverla al posto di un'assenza cambia la
2288
+ * semantica invece di ripulire il campo.
2289
+ */
2290
+ protected setField(field: keyof TNode & string, value: unknown): void;
2291
+ /** Numero da un campo di testo: vuoto o non numerico → assente, non `0`. */
2292
+ protected toNumber(value: string): number | undefined;
2293
+ /** Lettura tipizzata di un valore da un evento di input, senza `any` nei template. */
2294
+ protected valueOf(event: Event): string;
2295
+ protected checkedOf(event: Event): boolean;
2296
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeNodeInspectorBase<any>, never>;
2297
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<DpeNodeInspectorBase<any>, never, never, { "nodeName": { "alias": "nodeName"; "required": true; "isSignal": true; }; "node": { "alias": "node"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
2298
+ }
2299
+
2300
+ interface DpeDiagnosticRow {
2301
+ diagnostic: Diagnostic;
2302
+ location: string;
2303
+ /** Nodo a cui navigare, se il percorso permette di ricavarlo. */
2304
+ nodeName?: string;
2305
+ field?: string;
2306
+ isNotCompilable: boolean;
2307
+ isDialect: boolean;
2308
+ }
2309
+ declare class DpeDiagnosticsPanelComponent {
2310
+ private readonly store;
2311
+ /** Emesso quando la riga porta a un nodo: chi ascolta apre l'ispettore e inquadra il nodo. */
2312
+ readonly navigate: _angular_core.OutputEmitterRef<{
2313
+ nodeName: string;
2314
+ field?: string;
2315
+ }>;
2316
+ readonly hasResult: _angular_core.Signal<boolean>;
2317
+ readonly dialectLabel: _angular_core.Signal<string>;
2318
+ readonly rows: _angular_core.Signal<DpeDiagnosticRow[]>;
2319
+ readonly counts: _angular_core.Signal<{
2320
+ errors: number;
2321
+ warnings: number;
2322
+ infos: number;
2323
+ notCompilable: number;
2324
+ }>;
2325
+ /**
2326
+ * Emette **soltanto** l'intenzione: chi la riceve seleziona e inquadra. Selezionare anche da qui
2327
+ * significherebbe due scritture della selezione per un solo clic — la strada per due nodi
2328
+ * selezionati insieme — e un pannello che pilota il canvas invece di chiederglielo.
2329
+ */
2330
+ protected navigateTo(row: DpeDiagnosticRow): void;
2331
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeDiagnosticsPanelComponent, never>;
2332
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeDiagnosticsPanelComponent, "dpe-diagnostics-panel", never, {}, { "navigate": "navigate"; }, never, never, true, never>;
2333
+ }
2334
+
2335
+ interface DpeSchemaRow {
2336
+ nodeName: string;
2337
+ categoryLabel: string;
2338
+ isSelected: boolean;
2339
+ isCompilable: boolean;
2340
+ hasSchema: boolean;
2341
+ inputColumns: readonly DpeColumnInfo[];
2342
+ outputColumns: readonly DpeColumnInfo[];
2343
+ /** Colonne in uscita che non esistono in ingresso: alias nuovi o colonne prodotte dal nodo. */
2344
+ introduced: ReadonlySet<string>;
2345
+ /** Colonne in ingresso che non arrivano in uscita: eliminate o rinominate. */
2346
+ dropped: readonly string[];
2347
+ }
2348
+ declare class DpeSchemaPanelComponent {
2349
+ private readonly store;
2350
+ readonly hasResult: _angular_core.Signal<boolean>;
2351
+ readonly rows: _angular_core.Signal<DpeSchemaRow[]>;
2352
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeSchemaPanelComponent, never>;
2353
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeSchemaPanelComponent, "dpe-schema-panel", never, {}, {}, never, never, true, never>;
2354
+ }
2355
+
2356
+ interface DpeSqlSection {
2357
+ title: string;
2358
+ hint: string;
2359
+ writebacks: readonly DpeCompiledWriteback[];
2360
+ }
2361
+ declare class DpeSqlPreviewComponent {
2362
+ private readonly store;
2363
+ protected readonly validation: DpeValidationService;
2364
+ readonly result: _angular_core.Signal<_esfaenza_dpe_builder.DpeCompileResult | undefined>;
2365
+ readonly sections: _angular_core.Signal<DpeSqlSection[]>;
2366
+ readonly isEmpty: _angular_core.Signal<boolean>;
2367
+ /** Il valore di un parametro e' opaco: si mostra, non si converte. */
2368
+ protected display(value: unknown): string;
2369
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeSqlPreviewComponent, never>;
2370
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeSqlPreviewComponent, "dpe-sql-preview", never, {}, {}, never, never, true, never>;
2371
+ }
2372
+
2373
+ declare class DpeExpressionEditorComponent {
2374
+ readonly label: _angular_core.InputSignal<string>;
2375
+ readonly value: _angular_core.InputSignal<string | undefined>;
2376
+ readonly placeholder: _angular_core.InputSignal<string>;
2377
+ readonly dialect: _angular_core.InputSignal<SqlDialectKind>;
2378
+ /**
2379
+ * I nomi delle colonne a monte, **come suggerimento** e non come elenco chiuso: sono cio'
2380
+ * che il backend ha propagato, ma dentro l'espressione si puo' scrivere qualunque SQL.
2381
+ */
2382
+ readonly columns: _angular_core.InputSignal<readonly string[]>;
2383
+ readonly controlId: _angular_core.InputSignal<string>;
2384
+ readonly valueChange: _angular_core.OutputEmitterRef<string>;
2385
+ readonly dialectLabel: _angular_core.Signal<string>;
2386
+ /** Elenco troncato: dieci nomi sono un aiuto, cinquanta sono un muro di testo. */
2387
+ readonly columnHint: _angular_core.Signal<string>;
2388
+ protected text(event: Event): string;
2389
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeExpressionEditorComponent, never>;
2390
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeExpressionEditorComponent, "dpe-expression-editor", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "dialect": { "alias": "dialect"; "required": true; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "controlId": { "alias": "controlId"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
2391
+ }
2392
+
2393
+ declare class DpeColumnTypeEditorComponent {
2394
+ readonly value: _angular_core.InputSignal<ColumnType | undefined>;
2395
+ readonly controlId: _angular_core.InputSignal<string>;
2396
+ readonly valueChange: _angular_core.OutputEmitterRef<ColumnType>;
2397
+ protected readonly types: readonly LogicalType[];
2398
+ readonly kind: _angular_core.Signal<LogicalType>;
2399
+ readonly allowedValues: _angular_core.Signal<string>;
2400
+ protected onKind(kind: string): void;
2401
+ protected onNumber(field: 'length' | 'precision' | 'scale', raw: string): void;
2402
+ protected onAllowedValues(raw: string): void;
2403
+ protected text(event: Event): string;
2404
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeColumnTypeEditorComponent, never>;
2405
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeColumnTypeEditorComponent, "dpe-column-type-editor", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "controlId": { "alias": "controlId"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
2406
+ }
2407
+
2408
+ declare class DpeSelectValueDirective implements AfterViewChecked {
2409
+ private readonly element;
2410
+ readonly dpeValue: _angular_core.InputSignal<string | number | null | undefined>;
2411
+ ngAfterViewChecked(): void;
2412
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeSelectValueDirective, never>;
2413
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<DpeSelectValueDirective, "select[dpeValue]", never, { "dpeValue": { "alias": "dpeValue"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2414
+ }
2415
+
2416
+ declare class DpeNodeIconComponent {
2417
+ readonly collection: _angular_core.InputSignal<keyof _esfaenza_dpe_builder.DpeNodeCollectionMap>;
2418
+ protected readonly paths: _angular_core.Signal<readonly string[]>;
2419
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<DpeNodeIconComponent, never>;
2420
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<DpeNodeIconComponent, "dpe-node-icon", never, { "collection": { "alias": "collection"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
2421
+ }
2422
+
2423
+ export { DPE_API_ERROR_FALLBACK_MESSAGE, DPE_BUILDER_HTTP_CONFIG, DPE_DIALECT_LABELS, DPE_LAYOUT_KEY, DPE_NODE_CATEGORIES, DPE_NODE_COLLECTIONS, DPE_NODE_HEIGHT, DPE_NODE_ICON_PATHS, DPE_NODE_NOT_COMPILABLE, DPE_SOURCE_SLOTS, DpeApiError, DpeBuilderApi, DpeBuilderComponent, DpeCanvasComponent, DpeCatalogComponent, DpeCatalogStore, DpeColumnTypeEditorComponent, DpeDiagnosticsPanelComponent, DpeDocumentStore, DpeExpressionEditorComponent, DpeLayoutService, DpeMetadataStore, DpeNodeIconComponent, DpeNodeInspectorBase, DpeNodeInspectorComponent, DpeNodePaletteComponent, DpeSchemaPanelComponent, DpeSelectValueDirective, DpeSqlPreviewComponent, DpeValidationService, HttpDpeBuilderApi, diagnosticPathToString, dpeAllNodes, dpeBuildGraph, dpeCountReferences, dpeCreateCommandAvailability, dpeCreateNode, dpeDefinitionLevelDiagnostics, dpeDiagnosticField, dpeDiagnosticLocationLabel, dpeDiagnosticNodeName, dpeEdgeId, dpeEmptyDefinition, dpeFindNode, dpeGroupDiagnosticsByNode, dpeHasCompleteLayout, dpeInputPortId, dpeInputPorts, dpeIsDialectDiagnostic, dpeIsNotCompilable, dpeIsPrimitiveAvailable, dpeIsRectFullyVisible, dpeKnownNodeNames, dpeNodeCategory, dpeNodeIconFamily, dpeNodeIconFamilyClass, dpeNodeIconPaths, dpeNodeId, dpeNodeSourceReferences, dpeNodeSubtitle, dpeNodeWidth, dpeNodeWidthClass, dpeOutputPortId, dpeParseInputPortId, dpeParseNodeId, dpeParseOutputPortId, dpeProposeNodeName, dpeProposeWritebackSequence, dpeReadCapabilities, dpeReadNodePosition, dpeRenameNode, dpeWorstSeverity, dpeWriteNodePosition, dpeWriteSourceReference, provideDpeBuilderHttpApi };
2424
+ export type { AggregateField, AggregateFunction, AggregateNode, AppendNode, AtomicWritebackNode, AtomicWritebackRelationship, ColumnType, CsvArtifactOptions, CsvDelimiter, CsvSourceOptions, CustomNode, CustomNodeParameter, DataSourceField, DataSourceKind, DataSourceNode, DatePart, DeclaredField, DefinitionRunMode, DefinitionStatus, Diagnostic, DiagnosticPath, DiagnosticPathSegment, DiagnosticSeverity, DpeAnyNode, DpeApiErrorCategory, DpeBuilderHttpConfig, DpeCanvasEdge, DpeCanvasNode, DpeCanvasPort, DpeCapabilities, DpeColumnInfo, DpeCommandAvailability, DpeCompileResult, DpeCompiledWriteback, DpeDefinition, DpeDefinitionSummary, DpeEnvironment, DpeExtensible, DpeExtensionData, DpeFieldMappingInfo, DpeGraph, DpeGraphEdge, DpeGraphNode, DpeInputPort, DpeLayoutDirection, DpeLayoutEdgeInput, DpeLayoutNodeInput, DpeLayoutOptions, DpeLayoutPosition, DpeLocatedNode, DpeNode, DpeNodeCategory, DpeNodeCollectionMap, DpeNodeCollectionName, DpeNodeDiagnostics, DpeNodeIconFamily, DpeNodePaletteGroup, DpeNodePosition, DpeNodeSchemaInfo, DpeOptionalPrimitive, DpeParameter, DpeParameterValue, DpeRect, DpeSourceReference, DpeSourceSlot, DpeTableState, DpeValidateResult, DpeWritebackStep, ExpressionField, FieldDescriptor, FieldRelationship, FilterCriterion, FilterNode, FilterOperator, ForecastAccuracy, ForecastAggregationField, ForecastGroupField, ForecastModelType, ForecastNode, ForecastPeriodType, HierarchyPathNode, JoinKey, JoinKind, JoinNode, JoinResultField, JsonArtifactOptions, LogicalType, OrderByField, ParameterRole, SortDirection, SqlDialectKind, SqlParameterValue, SqlStatement, TableDescriptor, TableLookupOutcome, TableLookupResult, TableSummary, TransformKind, TransformNode, WritebackFieldMapping, WritebackFieldRole, WritebackNode, WritebackOperation, WritebackTargetKind };