| 105 | } |
| 106 | |
| 107 | async function validatePipes(client) { |
| 108 | const issues = []; |
| 109 | for (const pipeDef of PIPE_DEFINITIONS) { |
| 110 | try { |
| 111 | const pipe = await client.getPipe(pipeDef.name); |
| 112 | if (!pipe) { |
| 113 | issues.push(`Missing pipe ${pipeDef.name}`); |
| 114 | continue; |
| 115 | } |
| 116 | |
| 117 | if ((pipe.type || "").toLowerCase() !== "materialized") { |
| 118 | issues.push( |
| 119 | `Pipe ${pipeDef.name} is not materialized (type=${pipe.type ?? "unknown"}).`, |
| 120 | ); |
| 121 | continue; |
| 122 | } |
| 123 | |
| 124 | const materializedNode = pipe.nodes?.find( |
| 125 | (node) => |
| 126 | (node.type || "").toLowerCase() === "materialized" || |
| 127 | (node.node_type || "").toLowerCase() === "materialized" || |
| 128 | node.materialized, |
| 129 | ); |
| 130 | |
| 131 | const targetDatasource = |
| 132 | materializedNode?.tags?.materializing_target_datasource || |
| 133 | materializedNode?.materialized?.datasource || |
| 134 | materializedNode?.datasource || |
| 135 | materializedNode?.params?.datasource; |
| 136 | |
| 137 | if (targetDatasource !== pipeDef.targetDatasource) { |
| 138 | issues.push( |
| 139 | `Pipe ${pipeDef.name} does not target ${pipeDef.targetDatasource} (found ${targetDatasource ?? "unknown"}).`, |
| 140 | ); |
| 141 | continue; |
| 142 | } |
| 143 | |
| 144 | console.log(`✔ Pipe ${pipeDef.name} feeds ${pipeDef.targetDatasource}`); |
| 145 | } catch (error) { |
| 146 | const errorMessage = |
| 147 | error instanceof Error ? error.message : String(error); |
| 148 | const errorDetails = |
| 149 | error instanceof Error && error.cause ? ` (cause: ${error.cause})` : ""; |
| 150 | issues.push( |
| 151 | `Failed to inspect pipe ${pipeDef.name}: ${errorMessage}${errorDetails}`, |
| 152 | ); |
| 153 | } |
| 154 | } |
| 155 | return issues; |
| 156 | } |
| 157 | |
| 158 | async function main() { |
| 159 | try { |