Skip to content

Commit fc8fcd0

Browse files
committed
chore: add branded model string types
1 parent fe6f3ba commit fc8fcd0

File tree

7 files changed

+52
-23
lines changed

7 files changed

+52
-23
lines changed

vscode/react/src/components/graph/ModelColumns.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import { Popover, Transition } from '@headlessui/react'
4646
import { useApiColumnLineage } from '@/api/index'
4747
import SourceList from '@/components/sourceList/SourceList'
4848
import type { Lineage } from '@/domain/lineage'
49+
import type { ModelName } from '@/types/models'
4950

5051
export default function ModelColumns({
5152
nodeId,
@@ -732,5 +733,5 @@ function getColumnFromLineage(
732733
nodeId: string,
733734
columnName: string,
734735
): LineageColumn | undefined {
735-
return lineage?.[nodeId]?.columns?.[encodeURI(columnName)]
736+
return lineage?.[nodeId]?.columns?.[encodeURI(columnName) as ModelName]
736737
}

vscode/react/src/components/graph/help.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from './ModelNode'
1818
import type { Lineage } from '@/domain/lineage'
1919
import type { ConnectedNode } from '@/workers/lineage'
20+
import type { ModelName, ModelFQN } from '@/types/models'
2021

2122
export interface GraphNodeData {
2223
label: string
@@ -108,7 +109,7 @@ function getEdges(lineage: Record<string, Lineage> = {}): Edge[] {
108109
})
109110

110111
for (const targetColumnName in targetModel.columns) {
111-
const sourceModel = targetModel.columns[targetColumnName]
112+
const sourceModel = targetModel.columns[targetColumnName as ModelName]
112113

113114
if (isNil(sourceModel) || isNil(sourceModel.models)) continue
114115

@@ -210,7 +211,7 @@ function getNodeMap({
210211
node.targetPosition = Position.Left
211212
}
212213

213-
if (sources.has(node.id)) {
214+
if (sources.has(node.id as ModelFQN)) {
214215
node.sourcePosition = Position.Right
215216
}
216217

@@ -343,7 +344,7 @@ function mergeLineageWithColumns(
343344
}
344345

345346
// New Column Lineage delivers fresh data, so we can just assign it
346-
currentLineageModel.columns[targetColumnNameEncoded] = {
347+
currentLineageModel.columns[targetColumnNameEncoded as ModelName] = {
347348
expression: newLineageModelColumn.expression,
348349
source: newLineageModelColumn.source,
349350
models: {},
@@ -353,7 +354,7 @@ function mergeLineageWithColumns(
353354
if (isObjectEmpty(newLineageModelColumn.models)) continue
354355

355356
const currentLineageModelColumn =
356-
currentLineageModel.columns[targetColumnNameEncoded]!
357+
currentLineageModel.columns[targetColumnNameEncoded as ModelName]!
357358
const currentLineageModelColumnModels = currentLineageModelColumn.models
358359

359360
for (const sourceColumnName in newLineageModelColumn.models) {
@@ -371,7 +372,7 @@ function mergeLineageWithColumns(
371372
newLineageModelColumnModel,
372373
),
373374
),
374-
).map(encodeURI)
375+
).map((uri: string) => encodeURI(uri))
375376
}
376377
}
377378
}
@@ -481,7 +482,7 @@ function getLineageIndex(lineage: Record<string, Lineage> = {}): string {
481482

482483
if (isNotNil(columns)) {
483484
Object.keys(columns).forEach(columnName => {
484-
const column = columns[columnName]
485+
const column = columns[columnName as ModelName]
485486

486487
if (isNotNil(column) && isNotNil(column.models)) {
487488
Object.keys(column.models).forEach(m => allModels.add(m))

vscode/react/src/domain/lineage.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type LineageColumn } from '@/api/client'
2+
import type { ModelFQN, ModelName } from '@/types/models'
23

34
export interface Lineage {
4-
models: string[]
5-
columns?: Record<string, LineageColumn>
5+
models: ModelFQN[]
6+
columns?: Record<ModelName, LineageColumn>
67
}

vscode/react/src/domain/sqlmesh-model.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@ import {
88
type ModelDefaultCatalog,
99
type ModelDefinition,
1010
} from '@/api/client'
11+
import type { ModelFQN, ModelName, ModelPath } from '@/types/models'
1112
import { isArrayNotEmpty } from '@/utils/index'
1213
import { ModelInitial } from './initial'
1314
import type { Lineage } from './lineage'
1415

15-
export interface InitialSQLMeshModel extends Model {
16-
lineage?: Record<string, Lineage>
16+
export interface InitialSQLMeshModel
17+
extends Omit<Model, 'name' | 'fqn' | 'path' | 'full_path'> {
18+
name: ModelName
19+
fqn: ModelFQN
20+
path: ModelPath
21+
full_path: ModelPath
22+
lineage?: Record<ModelName, Lineage>
1723
}
1824

1925
export class ModelSQLMeshModel<
@@ -22,9 +28,10 @@ export class ModelSQLMeshModel<
2228
_details: ModelDetails = {}
2329
_detailsIndex: string = ''
2430

25-
name: string
26-
fqn: string
27-
path: string
31+
name: ModelName
32+
fqn: ModelFQN
33+
path: ModelPath
34+
full_path: ModelPath
2835
dialect: string
2936
type: ModelType
3037
columns: Column[]
@@ -46,10 +53,11 @@ export class ModelSQLMeshModel<
4653
},
4754
)
4855

49-
this.name = encodeURI(this.initial.name)
50-
this.fqn = encodeURI(this.initial.fqn)
56+
this.name = encodeURI(this.initial.name) as ModelName
57+
this.fqn = encodeURI(this.initial.fqn) as ModelFQN
5158
this.default_catalog = this.initial.default_catalog
52-
this.path = this.initial.path
59+
this.path = this.initial.path as ModelPath
60+
this.full_path = this.initial.full_path as ModelPath
5361
this.dialect = this.initial.dialect
5462
this.description = this.initial.description
5563
this.sql = this.initial.sql
@@ -127,17 +135,21 @@ export class ModelSQLMeshModel<
127135
} else if (key === 'details') {
128136
this.details = value as ModelDetails
129137
} else if (key === 'name') {
130-
this.name = encodeURI(value as string)
138+
this.name = encodeURI(value as string) as ModelName
131139
} else if (key === 'fqn') {
132-
this.fqn = encodeURI(value as string)
140+
this.fqn = encodeURI(value as string) as ModelFQN
133141
} else if (key === 'type') {
134142
this.type = value as ModelType
135143
} else if (key === 'default_catalog') {
136144
this.default_catalog = value as ModelDefaultCatalog
137145
} else if (key === 'description') {
138146
this.description = value as ModelDescription
139147
} else if (key in this) {
140-
this[key as 'path' | 'dialect' | 'sql'] = value as string
148+
if (key === 'path' || key === 'full_path') {
149+
;(this as any)[key] = value as ModelPath
150+
} else {
151+
;(this as any)[key] = value as string
152+
}
141153
}
142154
}
143155
}

vscode/react/src/pages/lineage.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type { VSCodeEvent } from '@bus/callbacks'
1616
import { URI } from 'vscode-uri'
1717
import type { Model } from '@/api/client'
1818
import { useRpc } from '@/utils/rpc'
19+
import type { ModelName, ModelFQN, ModelPath } from '@/types/models'
1920

2021
export function LineagePage() {
2122
const { emit } = useEventBus()
@@ -198,7 +199,13 @@ export function LineageComponentFromWeb({
198199
}
199200

200201
const sqlmModel = new ModelSQLMeshModel()
201-
sqlmModel.update(model)
202+
sqlmModel.update({
203+
...model,
204+
name: model.name as ModelName,
205+
fqn: model.fqn as ModelFQN,
206+
path: model.path as ModelPath,
207+
full_path: model.full_path as ModelPath,
208+
})
202209

203210
return (
204211
<div className="h-[100vh] w-[100vw]">

vscode/react/src/types/models.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export type Brand<T, B extends string> = T & { __brand: B }
2+
3+
export type ModelName = Brand<string, 'ModelName'>
4+
export type ModelFQN = Brand<string, 'ModelFQN'>
5+
export type ModelURI = Brand<string, 'ModelURI'>
6+
export type ModelPath = Brand<string, 'ModelPath'>

vscode/react/src/workers/lineage.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { isFalse, isNil, isStringEmptyOrNil, toID } from '@/utils/index'
22
import { type Lineage } from '@/domain/lineage'
3+
import type { ModelFQN } from '@/types/models'
34

45
export interface ConnectedNode {
56
id?: string
@@ -47,7 +48,7 @@ async function mergeLineageWithModels(
4748
key = encodeURI(key)
4849

4950
acc[key] = {
50-
models: models.map(encodeURI),
51+
models: models.map(encodeURI) as ModelFQN[],
5152
columns: currentLineage?.[key]?.columns ?? undefined,
5253
}
5354

@@ -88,7 +89,7 @@ function getConnectedNodes(
8889

8990
if (isDownstream) {
9091
models = Object.keys(lineage).filter(key =>
91-
lineage[key]!.models.includes(node),
92+
lineage[key]!.models.includes(node as ModelFQN),
9293
)
9394
} else {
9495
models = lineage[node]?.models ?? []

0 commit comments

Comments
 (0)