@tinybirdco/sdk 0.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.
Files changed (258) hide show
  1. package/README.md +518 -0
  2. package/bin/tinybird.js +7 -0
  3. package/dist/api/branches.d.ts +98 -0
  4. package/dist/api/branches.d.ts.map +1 -0
  5. package/dist/api/branches.js +203 -0
  6. package/dist/api/branches.js.map +1 -0
  7. package/dist/api/branches.test.d.ts +2 -0
  8. package/dist/api/branches.test.d.ts.map +1 -0
  9. package/dist/api/branches.test.js +286 -0
  10. package/dist/api/branches.test.js.map +1 -0
  11. package/dist/api/build.d.ts +130 -0
  12. package/dist/api/build.d.ts.map +1 -0
  13. package/dist/api/build.js +143 -0
  14. package/dist/api/build.js.map +1 -0
  15. package/dist/api/build.test.d.ts +2 -0
  16. package/dist/api/build.test.d.ts.map +1 -0
  17. package/dist/api/build.test.js +138 -0
  18. package/dist/api/build.test.js.map +1 -0
  19. package/dist/api/deploy.d.ts +39 -0
  20. package/dist/api/deploy.d.ts.map +1 -0
  21. package/dist/api/deploy.js +135 -0
  22. package/dist/api/deploy.js.map +1 -0
  23. package/dist/api/deploy.test.d.ts +2 -0
  24. package/dist/api/deploy.test.d.ts.map +1 -0
  25. package/dist/api/deploy.test.js +118 -0
  26. package/dist/api/deploy.test.js.map +1 -0
  27. package/dist/api/workspaces.d.ts +46 -0
  28. package/dist/api/workspaces.d.ts.map +1 -0
  29. package/dist/api/workspaces.js +39 -0
  30. package/dist/api/workspaces.js.map +1 -0
  31. package/dist/api/workspaces.test.d.ts +2 -0
  32. package/dist/api/workspaces.test.d.ts.map +1 -0
  33. package/dist/api/workspaces.test.js +65 -0
  34. package/dist/api/workspaces.test.js.map +1 -0
  35. package/dist/cli/auth.d.ts +86 -0
  36. package/dist/cli/auth.d.ts.map +1 -0
  37. package/dist/cli/auth.js +284 -0
  38. package/dist/cli/auth.js.map +1 -0
  39. package/dist/cli/branch-store.d.ts +53 -0
  40. package/dist/cli/branch-store.d.ts.map +1 -0
  41. package/dist/cli/branch-store.js +91 -0
  42. package/dist/cli/branch-store.js.map +1 -0
  43. package/dist/cli/branch-store.test.d.ts +2 -0
  44. package/dist/cli/branch-store.test.d.ts.map +1 -0
  45. package/dist/cli/branch-store.test.js +115 -0
  46. package/dist/cli/branch-store.test.js.map +1 -0
  47. package/dist/cli/commands/branch.d.ts +82 -0
  48. package/dist/cli/commands/branch.d.ts.map +1 -0
  49. package/dist/cli/commands/branch.js +215 -0
  50. package/dist/cli/commands/branch.js.map +1 -0
  51. package/dist/cli/commands/build.d.ts +43 -0
  52. package/dist/cli/commands/build.d.ts.map +1 -0
  53. package/dist/cli/commands/build.js +138 -0
  54. package/dist/cli/commands/build.js.map +1 -0
  55. package/dist/cli/commands/dev.d.ts +78 -0
  56. package/dist/cli/commands/dev.d.ts.map +1 -0
  57. package/dist/cli/commands/dev.js +226 -0
  58. package/dist/cli/commands/dev.js.map +1 -0
  59. package/dist/cli/commands/init.d.ts +45 -0
  60. package/dist/cli/commands/init.d.ts.map +1 -0
  61. package/dist/cli/commands/init.js +277 -0
  62. package/dist/cli/commands/init.js.map +1 -0
  63. package/dist/cli/commands/init.test.d.ts +2 -0
  64. package/dist/cli/commands/init.test.d.ts.map +1 -0
  65. package/dist/cli/commands/init.test.js +158 -0
  66. package/dist/cli/commands/init.test.js.map +1 -0
  67. package/dist/cli/commands/login.d.ts +37 -0
  68. package/dist/cli/commands/login.d.ts.map +1 -0
  69. package/dist/cli/commands/login.js +64 -0
  70. package/dist/cli/commands/login.js.map +1 -0
  71. package/dist/cli/config.d.ts +114 -0
  72. package/dist/cli/config.d.ts.map +1 -0
  73. package/dist/cli/config.js +258 -0
  74. package/dist/cli/config.js.map +1 -0
  75. package/dist/cli/config.test.d.ts +2 -0
  76. package/dist/cli/config.test.d.ts.map +1 -0
  77. package/dist/cli/config.test.js +243 -0
  78. package/dist/cli/config.test.js.map +1 -0
  79. package/dist/cli/env.d.ts +29 -0
  80. package/dist/cli/env.d.ts.map +1 -0
  81. package/dist/cli/env.js +66 -0
  82. package/dist/cli/env.js.map +1 -0
  83. package/dist/cli/git.d.ts +29 -0
  84. package/dist/cli/git.d.ts.map +1 -0
  85. package/dist/cli/git.js +114 -0
  86. package/dist/cli/git.js.map +1 -0
  87. package/dist/cli/git.test.d.ts +2 -0
  88. package/dist/cli/git.test.d.ts.map +1 -0
  89. package/dist/cli/git.test.js +125 -0
  90. package/dist/cli/git.test.js.map +1 -0
  91. package/dist/cli/index.d.ts +7 -0
  92. package/dist/cli/index.d.ts.map +1 -0
  93. package/dist/cli/index.js +337 -0
  94. package/dist/cli/index.js.map +1 -0
  95. package/dist/cli/utils/schema-validation.d.ts +95 -0
  96. package/dist/cli/utils/schema-validation.d.ts.map +1 -0
  97. package/dist/cli/utils/schema-validation.js +175 -0
  98. package/dist/cli/utils/schema-validation.js.map +1 -0
  99. package/dist/cli/utils/schema-validation.test.d.ts +5 -0
  100. package/dist/cli/utils/schema-validation.test.d.ts.map +1 -0
  101. package/dist/cli/utils/schema-validation.test.js +173 -0
  102. package/dist/cli/utils/schema-validation.test.js.map +1 -0
  103. package/dist/client/base.d.ts +116 -0
  104. package/dist/client/base.d.ts.map +1 -0
  105. package/dist/client/base.js +328 -0
  106. package/dist/client/base.js.map +1 -0
  107. package/dist/client/types.d.ts +137 -0
  108. package/dist/client/types.d.ts.map +1 -0
  109. package/dist/client/types.js +43 -0
  110. package/dist/client/types.js.map +1 -0
  111. package/dist/generator/client.d.ts +44 -0
  112. package/dist/generator/client.d.ts.map +1 -0
  113. package/dist/generator/client.js +144 -0
  114. package/dist/generator/client.js.map +1 -0
  115. package/dist/generator/datasource.d.ts +57 -0
  116. package/dist/generator/datasource.d.ts.map +1 -0
  117. package/dist/generator/datasource.js +169 -0
  118. package/dist/generator/datasource.js.map +1 -0
  119. package/dist/generator/datasource.test.d.ts +2 -0
  120. package/dist/generator/datasource.test.d.ts.map +1 -0
  121. package/dist/generator/datasource.test.js +254 -0
  122. package/dist/generator/datasource.test.js.map +1 -0
  123. package/dist/generator/index.d.ts +131 -0
  124. package/dist/generator/index.d.ts.map +1 -0
  125. package/dist/generator/index.js +121 -0
  126. package/dist/generator/index.js.map +1 -0
  127. package/dist/generator/index.test.d.ts +2 -0
  128. package/dist/generator/index.test.d.ts.map +1 -0
  129. package/dist/generator/index.test.js +175 -0
  130. package/dist/generator/index.test.js.map +1 -0
  131. package/dist/generator/loader.d.ts +156 -0
  132. package/dist/generator/loader.d.ts.map +1 -0
  133. package/dist/generator/loader.js +295 -0
  134. package/dist/generator/loader.js.map +1 -0
  135. package/dist/generator/pipe.d.ts +72 -0
  136. package/dist/generator/pipe.d.ts.map +1 -0
  137. package/dist/generator/pipe.js +174 -0
  138. package/dist/generator/pipe.js.map +1 -0
  139. package/dist/generator/pipe.test.d.ts +2 -0
  140. package/dist/generator/pipe.test.d.ts.map +1 -0
  141. package/dist/generator/pipe.test.js +393 -0
  142. package/dist/generator/pipe.test.js.map +1 -0
  143. package/dist/index.d.ts +74 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +73 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/infer/index.d.ts +202 -0
  148. package/dist/infer/index.d.ts.map +1 -0
  149. package/dist/infer/index.js +5 -0
  150. package/dist/infer/index.js.map +1 -0
  151. package/dist/schema/datasource.d.ts +135 -0
  152. package/dist/schema/datasource.d.ts.map +1 -0
  153. package/dist/schema/datasource.js +105 -0
  154. package/dist/schema/datasource.js.map +1 -0
  155. package/dist/schema/datasource.test.d.ts +2 -0
  156. package/dist/schema/datasource.test.d.ts.map +1 -0
  157. package/dist/schema/datasource.test.js +142 -0
  158. package/dist/schema/datasource.test.js.map +1 -0
  159. package/dist/schema/engines.d.ts +157 -0
  160. package/dist/schema/engines.d.ts.map +1 -0
  161. package/dist/schema/engines.js +155 -0
  162. package/dist/schema/engines.js.map +1 -0
  163. package/dist/schema/engines.test.d.ts +2 -0
  164. package/dist/schema/engines.test.d.ts.map +1 -0
  165. package/dist/schema/engines.test.js +221 -0
  166. package/dist/schema/engines.test.js.map +1 -0
  167. package/dist/schema/params.d.ts +106 -0
  168. package/dist/schema/params.d.ts.map +1 -0
  169. package/dist/schema/params.js +138 -0
  170. package/dist/schema/params.js.map +1 -0
  171. package/dist/schema/params.test.d.ts +2 -0
  172. package/dist/schema/params.test.d.ts.map +1 -0
  173. package/dist/schema/params.test.js +175 -0
  174. package/dist/schema/params.test.js.map +1 -0
  175. package/dist/schema/pipe.d.ts +436 -0
  176. package/dist/schema/pipe.d.ts.map +1 -0
  177. package/dist/schema/pipe.js +484 -0
  178. package/dist/schema/pipe.js.map +1 -0
  179. package/dist/schema/pipe.test.d.ts +2 -0
  180. package/dist/schema/pipe.test.d.ts.map +1 -0
  181. package/dist/schema/pipe.test.js +488 -0
  182. package/dist/schema/pipe.test.js.map +1 -0
  183. package/dist/schema/project.d.ts +202 -0
  184. package/dist/schema/project.d.ts.map +1 -0
  185. package/dist/schema/project.js +188 -0
  186. package/dist/schema/project.js.map +1 -0
  187. package/dist/schema/project.test.d.ts +2 -0
  188. package/dist/schema/project.test.d.ts.map +1 -0
  189. package/dist/schema/project.test.js +180 -0
  190. package/dist/schema/project.test.js.map +1 -0
  191. package/dist/schema/types.d.ts +140 -0
  192. package/dist/schema/types.d.ts.map +1 -0
  193. package/dist/schema/types.js +174 -0
  194. package/dist/schema/types.js.map +1 -0
  195. package/dist/schema/types.test.d.ts +2 -0
  196. package/dist/schema/types.test.d.ts.map +1 -0
  197. package/dist/schema/types.test.js +176 -0
  198. package/dist/schema/types.test.js.map +1 -0
  199. package/dist/test/handlers.d.ts +58 -0
  200. package/dist/test/handlers.d.ts.map +1 -0
  201. package/dist/test/handlers.js +62 -0
  202. package/dist/test/handlers.js.map +1 -0
  203. package/dist/test/setup.d.ts +5 -0
  204. package/dist/test/setup.d.ts.map +1 -0
  205. package/dist/test/setup.js +11 -0
  206. package/dist/test/setup.js.map +1 -0
  207. package/package.json +57 -0
  208. package/src/api/branches.test.ts +377 -0
  209. package/src/api/branches.ts +334 -0
  210. package/src/api/build.test.ts +216 -0
  211. package/src/api/build.ts +266 -0
  212. package/src/api/deploy.test.ts +193 -0
  213. package/src/api/deploy.ts +163 -0
  214. package/src/api/workspaces.test.ts +81 -0
  215. package/src/api/workspaces.ts +77 -0
  216. package/src/cli/auth.ts +358 -0
  217. package/src/cli/branch-store.test.ts +139 -0
  218. package/src/cli/branch-store.ts +137 -0
  219. package/src/cli/commands/branch.ts +306 -0
  220. package/src/cli/commands/build.ts +183 -0
  221. package/src/cli/commands/dev.ts +334 -0
  222. package/src/cli/commands/init.test.ts +249 -0
  223. package/src/cli/commands/init.ts +323 -0
  224. package/src/cli/commands/login.ts +98 -0
  225. package/src/cli/config.test.ts +359 -0
  226. package/src/cli/config.ts +335 -0
  227. package/src/cli/env.ts +86 -0
  228. package/src/cli/git.test.ts +147 -0
  229. package/src/cli/git.ts +125 -0
  230. package/src/cli/index.ts +382 -0
  231. package/src/cli/utils/schema-validation.test.ts +222 -0
  232. package/src/cli/utils/schema-validation.ts +272 -0
  233. package/src/client/base.ts +414 -0
  234. package/src/client/types.ts +165 -0
  235. package/src/generator/client.ts +194 -0
  236. package/src/generator/datasource.test.ts +297 -0
  237. package/src/generator/datasource.ts +217 -0
  238. package/src/generator/index.test.ts +209 -0
  239. package/src/generator/index.ts +203 -0
  240. package/src/generator/loader.ts +406 -0
  241. package/src/generator/pipe.test.ts +441 -0
  242. package/src/generator/pipe.ts +220 -0
  243. package/src/index.ts +191 -0
  244. package/src/infer/index.ts +247 -0
  245. package/src/schema/datasource.test.ts +187 -0
  246. package/src/schema/datasource.ts +195 -0
  247. package/src/schema/engines.test.ts +247 -0
  248. package/src/schema/engines.ts +271 -0
  249. package/src/schema/params.test.ts +208 -0
  250. package/src/schema/params.ts +249 -0
  251. package/src/schema/pipe.test.ts +588 -0
  252. package/src/schema/pipe.ts +832 -0
  253. package/src/schema/project.test.ts +236 -0
  254. package/src/schema/project.ts +394 -0
  255. package/src/schema/types.test.ts +212 -0
  256. package/src/schema/types.ts +366 -0
  257. package/src/test/handlers.ts +79 -0
  258. package/src/test/setup.ts +13 -0
package/src/index.ts ADDED
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @tinybirdco/sdk - TypeScript SDK for Tinybird Forward
3
+ *
4
+ * Define datasources and pipes as TypeScript with full type safety.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import {
9
+ * defineDatasource,
10
+ * definePipe,
11
+ * defineProject,
12
+ * node,
13
+ * t,
14
+ * p,
15
+ * engine,
16
+ * createClient,
17
+ * } from '@tinybirdco/sdk';
18
+ *
19
+ * // Define a datasource
20
+ * const events = defineDatasource('events', {
21
+ * schema: {
22
+ * timestamp: t.dateTime(),
23
+ * user_id: t.string(),
24
+ * event_type: t.string().lowCardinality(),
25
+ * },
26
+ * engine: engine.mergeTree({
27
+ * sortingKey: ['user_id', 'timestamp'],
28
+ * }),
29
+ * });
30
+ *
31
+ * // Define a pipe
32
+ * const topEvents = definePipe('top_events', {
33
+ * params: {
34
+ * limit: p.int32().optional(10),
35
+ * },
36
+ * nodes: [
37
+ * node({
38
+ * name: 'aggregated',
39
+ * sql: 'SELECT event_type, count() as cnt FROM events GROUP BY event_type LIMIT {{Int32(limit, 10)}}',
40
+ * }),
41
+ * ],
42
+ * output: {
43
+ * event_type: t.string(),
44
+ * cnt: t.uint64(),
45
+ * },
46
+ * endpoint: true,
47
+ * });
48
+ *
49
+ * // Create project
50
+ * export default defineProject({
51
+ * datasources: { events },
52
+ * pipes: { topEvents },
53
+ * });
54
+ * ```
55
+ */
56
+
57
+ // ============ Schema Types ============
58
+ export { t } from "./schema/types.js";
59
+ export type {
60
+ TypeValidator,
61
+ AnyTypeValidator,
62
+ TypeModifiers,
63
+ InferType,
64
+ TinybirdType,
65
+ } from "./schema/types.js";
66
+ export {
67
+ isTypeValidator,
68
+ getTinybirdType,
69
+ getModifiers,
70
+ } from "./schema/types.js";
71
+
72
+ // ============ Parameter Types ============
73
+ export { p } from "./schema/params.js";
74
+ export type {
75
+ ParamValidator,
76
+ AnyParamValidator,
77
+ InferParamType,
78
+ } from "./schema/params.js";
79
+ export {
80
+ isParamValidator,
81
+ getParamTinybirdType,
82
+ isParamRequired,
83
+ getParamDefault,
84
+ getParamDescription,
85
+ } from "./schema/params.js";
86
+
87
+ // ============ Engine Configurations ============
88
+ export { engine, getEngineClause, getSortingKey, getPrimaryKey } from "./schema/engines.js";
89
+ export type {
90
+ EngineConfig,
91
+ BaseMergeTreeConfig,
92
+ MergeTreeConfig,
93
+ ReplacingMergeTreeConfig,
94
+ SummingMergeTreeConfig,
95
+ AggregatingMergeTreeConfig,
96
+ CollapsingMergeTreeConfig,
97
+ VersionedCollapsingMergeTreeConfig,
98
+ } from "./schema/engines.js";
99
+
100
+ // ============ Datasource ============
101
+ export { defineDatasource, isDatasourceDefinition, column, getColumnType, getColumnJsonPath, getColumnNames } from "./schema/datasource.js";
102
+ export type {
103
+ DatasourceDefinition,
104
+ DatasourceOptions,
105
+ SchemaDefinition,
106
+ ColumnDefinition,
107
+ TokenConfig,
108
+ ExtractSchema,
109
+ } from "./schema/datasource.js";
110
+
111
+ // ============ Pipe ============
112
+ export {
113
+ definePipe,
114
+ defineEndpoint,
115
+ defineMaterializedView,
116
+ defineCopyPipe,
117
+ node,
118
+ isPipeDefinition,
119
+ isNodeDefinition,
120
+ getEndpointConfig,
121
+ getMaterializedConfig,
122
+ getCopyConfig,
123
+ isMaterializedView,
124
+ isCopyPipe,
125
+ getNodeNames,
126
+ getNode,
127
+ sql,
128
+ } from "./schema/pipe.js";
129
+ export type {
130
+ PipeDefinition,
131
+ PipeOptions,
132
+ EndpointOptions,
133
+ CopyPipeOptions,
134
+ CopyConfig,
135
+ NodeDefinition,
136
+ NodeOptions,
137
+ ParamsDefinition,
138
+ OutputDefinition,
139
+ EndpointConfig,
140
+ MaterializedConfig,
141
+ MaterializedViewOptions,
142
+ PipeTokenConfig,
143
+ ExtractParams,
144
+ ExtractOutput,
145
+ } from "./schema/pipe.js";
146
+
147
+ // ============ Project ============
148
+ export { defineProject, isProjectDefinition, getDatasourceNames, getPipeNames, getDatasource, getPipe, createTinybirdClient } from "./schema/project.js";
149
+ export type {
150
+ ProjectDefinition,
151
+ ProjectConfig,
152
+ ProjectClient,
153
+ TinybirdClientConfig,
154
+ DatasourcesDefinition,
155
+ PipesDefinition,
156
+ ExtractDatasources,
157
+ ExtractPipes,
158
+ DataModel,
159
+ } from "./schema/project.js";
160
+
161
+ // ============ Type Inference ============
162
+ export type {
163
+ Infer,
164
+ InferRow,
165
+ InferParams,
166
+ InferOutput,
167
+ InferOutputRow,
168
+ InferEvent,
169
+ PartialRow,
170
+ InferSchema,
171
+ InferTinybirdTypes,
172
+ InferMaterializedTarget,
173
+ InferMaterializedTargetRow,
174
+ IsMaterializedPipe,
175
+ } from "./infer/index.js";
176
+
177
+ // ============ Client ============
178
+ export { TinybirdClient, createClient } from "./client/base.js";
179
+ export { TinybirdError } from "./client/types.js";
180
+ export type {
181
+ ClientConfig,
182
+ QueryResult,
183
+ IngestResult,
184
+ QueryOptions,
185
+ IngestOptions,
186
+ ColumnMeta,
187
+ QueryStatistics,
188
+ TinybirdErrorResponse,
189
+ TypedPipeEndpoint,
190
+ TypedDatasourceIngest,
191
+ } from "./client/types.js";
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Type inference utilities for extracting TypeScript types from Tinybird definitions
3
+ */
4
+
5
+ import type { TypeValidator, TypeModifiers } from "../schema/types.js";
6
+ import type { ParamValidator } from "../schema/params.js";
7
+ import type { DatasourceDefinition, SchemaDefinition, ColumnDefinition } from "../schema/datasource.js";
8
+ import type { PipeDefinition, ParamsDefinition, OutputDefinition } from "../schema/pipe.js";
9
+
10
+ /**
11
+ * Extract the TypeScript type from a type validator
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { t, Infer } from '@tinybirdco/sdk';
16
+ *
17
+ * const myType = t.string();
18
+ * type MyType = Infer<typeof myType>; // string
19
+ *
20
+ * const myArray = t.array(t.int32());
21
+ * type MyArray = Infer<typeof myArray>; // number[]
22
+ * ```
23
+ */
24
+ export type Infer<T> = T extends TypeValidator<infer U, string, TypeModifiers>
25
+ ? U
26
+ : T extends ParamValidator<infer U, string, boolean>
27
+ ? U
28
+ : never;
29
+
30
+ /**
31
+ * Infer a single column type, handling both raw validators and column definitions
32
+ */
33
+ type InferColumn<T> = T extends TypeValidator<infer U, string, TypeModifiers>
34
+ ? U
35
+ : T extends { type: TypeValidator<infer U, string, TypeModifiers> }
36
+ ? U
37
+ : never;
38
+
39
+ /**
40
+ * Extract a row type from a datasource definition
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { defineDatasource, t, InferRow } from '@tinybirdco/sdk';
45
+ *
46
+ * const events = defineDatasource('events', {
47
+ * schema: {
48
+ * id: t.string(),
49
+ * count: t.int32(),
50
+ * timestamp: t.dateTime(),
51
+ * },
52
+ * });
53
+ *
54
+ * type EventRow = InferRow<typeof events>;
55
+ * // { id: string; count: number; timestamp: Date }
56
+ * ```
57
+ */
58
+ export type InferRow<T> = T extends DatasourceDefinition<infer S>
59
+ ? { [K in keyof S]: InferColumn<S[K]> }
60
+ : never;
61
+
62
+ /**
63
+ * Infer a single parameter type, respecting required/optional
64
+ */
65
+ type InferSingleParam<T> = T extends ParamValidator<infer U, string, infer R>
66
+ ? R extends true
67
+ ? U
68
+ : U | undefined
69
+ : never;
70
+
71
+ /**
72
+ * Extract the required parameter keys from a params definition
73
+ */
74
+ type RequiredParamKeys<T extends ParamsDefinition> = {
75
+ [K in keyof T]: T[K] extends ParamValidator<unknown, string, true> ? K : never;
76
+ }[keyof T];
77
+
78
+ /**
79
+ * Extract the optional parameter keys from a params definition
80
+ */
81
+ type OptionalParamKeys<T extends ParamsDefinition> = {
82
+ [K in keyof T]: T[K] extends ParamValidator<unknown, string, false> ? K : never;
83
+ }[keyof T];
84
+
85
+ /**
86
+ * Extract the params type from a pipe definition
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * import { definePipe, p, InferParams } from '@tinybirdco/sdk';
91
+ *
92
+ * const myPipe = definePipe('my_pipe', {
93
+ * params: {
94
+ * userId: p.string(),
95
+ * limit: p.int32().optional(10),
96
+ * },
97
+ * nodes: [...],
98
+ * output: {...},
99
+ * });
100
+ *
101
+ * type MyParams = InferParams<typeof myPipe>;
102
+ * // { userId: string; limit?: number }
103
+ * ```
104
+ */
105
+ export type InferParams<T> = T extends PipeDefinition<infer P, OutputDefinition>
106
+ ? {
107
+ [K in RequiredParamKeys<P>]: InferSingleParam<P[K]>;
108
+ } & {
109
+ [K in OptionalParamKeys<P>]?: InferSingleParam<P[K]>;
110
+ }
111
+ : never;
112
+
113
+ /**
114
+ * Extract the output type (single row) from a pipe definition
115
+ *
116
+ * @example
117
+ * ```ts
118
+ * import { definePipe, t, InferOutput } from '@tinybirdco/sdk';
119
+ *
120
+ * const myPipe = definePipe('my_pipe', {
121
+ * params: {},
122
+ * nodes: [...],
123
+ * output: {
124
+ * name: t.string(),
125
+ * count: t.uint64(),
126
+ * },
127
+ * });
128
+ *
129
+ * type MyOutput = InferOutput<typeof myPipe>;
130
+ * // { name: string; count: number }[]
131
+ * ```
132
+ */
133
+ export type InferOutput<T> = T extends PipeDefinition<ParamsDefinition, infer O>
134
+ ? { [K in keyof O]: InferColumn<O[K]> }[]
135
+ : never;
136
+
137
+ /**
138
+ * Extract a single output row type (without array wrapper)
139
+ */
140
+ export type InferOutputRow<T> = T extends PipeDefinition<ParamsDefinition, infer O>
141
+ ? { [K in keyof O]: InferColumn<O[K]> }
142
+ : never;
143
+
144
+ /**
145
+ * Infer the event type for ingestion (same as row type)
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * import { defineDatasource, t, InferEvent } from '@tinybirdco/sdk';
150
+ *
151
+ * const events = defineDatasource('events', {
152
+ * schema: {
153
+ * id: t.string(),
154
+ * timestamp: t.dateTime(),
155
+ * },
156
+ * });
157
+ *
158
+ * type Event = InferEvent<typeof events>;
159
+ * // { id: string; timestamp: Date }
160
+ *
161
+ * // Use for type-safe event ingestion
162
+ * const event: Event = { id: '123', timestamp: new Date() };
163
+ * ```
164
+ */
165
+ export type InferEvent<T> = InferRow<T>;
166
+
167
+ /**
168
+ * Make all properties of InferRow optional (for partial updates)
169
+ */
170
+ export type PartialRow<T> = T extends DatasourceDefinition<infer S>
171
+ ? Partial<{ [K in keyof S]: InferColumn<S[K]> }>
172
+ : never;
173
+
174
+ /**
175
+ * Extract the schema definition type from a datasource
176
+ */
177
+ export type InferSchema<T> = T extends DatasourceDefinition<infer S> ? S : never;
178
+
179
+ /**
180
+ * Helper type to get the Tinybird type string for a schema
181
+ * Handles both raw TypeValidators and ColumnDefinition wrappers
182
+ */
183
+ export type InferTinybirdTypes<T extends SchemaDefinition> = {
184
+ [K in keyof T]: T[K] extends ColumnDefinition<infer V>
185
+ ? V extends TypeValidator<unknown, infer TB, TypeModifiers>
186
+ ? TB
187
+ : never
188
+ : T[K] extends TypeValidator<unknown, infer TB, TypeModifiers>
189
+ ? TB
190
+ : never;
191
+ };
192
+
193
+ /**
194
+ * Extract the target datasource from a materialized view pipe
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * import { definePipe, defineDatasource, t, engine, InferMaterializedTarget } from '@tinybirdco/sdk';
199
+ *
200
+ * const salesByHour = defineDatasource('sales_by_hour', {
201
+ * schema: { day: t.date(), total: t.uint64() },
202
+ * engine: engine.aggregatingMergeTree({ sortingKey: ['day'] }),
203
+ * });
204
+ *
205
+ * const salesMv = definePipe('sales_mv', {
206
+ * nodes: [...],
207
+ * output: { day: t.date(), total: t.uint64() },
208
+ * materialized: { datasource: salesByHour },
209
+ * });
210
+ *
211
+ * type Target = InferMaterializedTarget<typeof salesMv>;
212
+ * // typeof salesByHour
213
+ * ```
214
+ */
215
+ export type InferMaterializedTarget<T> = T extends PipeDefinition<
216
+ ParamsDefinition,
217
+ OutputDefinition
218
+ >
219
+ ? T["options"]["materialized"] extends { datasource: infer D }
220
+ ? D extends DatasourceDefinition<SchemaDefinition>
221
+ ? D
222
+ : never
223
+ : never
224
+ : never;
225
+
226
+ /**
227
+ * Extract the target datasource row type from a materialized view pipe
228
+ *
229
+ * @example
230
+ * ```ts
231
+ * type TargetRow = InferMaterializedTargetRow<typeof salesMv>;
232
+ * // { day: Date; total: number }
233
+ * ```
234
+ */
235
+ export type InferMaterializedTargetRow<T> = InferRow<InferMaterializedTarget<T>>;
236
+
237
+ /**
238
+ * Check if a pipe definition is a materialized view (type-level)
239
+ */
240
+ export type IsMaterializedPipe<T> = T extends PipeDefinition<
241
+ ParamsDefinition,
242
+ OutputDefinition
243
+ >
244
+ ? T["options"]["materialized"] extends { datasource: DatasourceDefinition<SchemaDefinition> }
245
+ ? true
246
+ : false
247
+ : false;
@@ -0,0 +1,187 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import {
3
+ defineDatasource,
4
+ isDatasourceDefinition,
5
+ getColumnType,
6
+ getColumnJsonPath,
7
+ getColumnNames,
8
+ column,
9
+ } from "./datasource.js";
10
+ import { t } from "./types.js";
11
+ import { engine } from "./engines.js";
12
+
13
+ describe("Datasource Schema", () => {
14
+ describe("defineDatasource", () => {
15
+ it("creates a datasource with required fields", () => {
16
+ const ds = defineDatasource("events", {
17
+ schema: {
18
+ id: t.string(),
19
+ timestamp: t.dateTime(),
20
+ },
21
+ });
22
+
23
+ expect(ds._name).toBe("events");
24
+ expect(ds._type).toBe("datasource");
25
+ expect(ds.options.schema).toBeDefined();
26
+ });
27
+
28
+ it("creates a datasource with description", () => {
29
+ const ds = defineDatasource("events", {
30
+ description: "Event tracking data",
31
+ schema: {
32
+ id: t.string(),
33
+ },
34
+ });
35
+
36
+ expect(ds.options.description).toBe("Event tracking data");
37
+ });
38
+
39
+ it("creates a datasource with engine configuration", () => {
40
+ const ds = defineDatasource("events", {
41
+ schema: {
42
+ id: t.string(),
43
+ timestamp: t.dateTime(),
44
+ },
45
+ engine: engine.mergeTree({
46
+ sortingKey: ["id", "timestamp"],
47
+ partitionKey: "toYYYYMM(timestamp)",
48
+ }),
49
+ });
50
+
51
+ expect(ds.options.engine).toBeDefined();
52
+ expect(ds.options.engine?.type).toBe("MergeTree");
53
+ });
54
+
55
+ it("throws error for invalid datasource name", () => {
56
+ expect(() =>
57
+ defineDatasource("123invalid", {
58
+ schema: { id: t.string() },
59
+ })
60
+ ).toThrow("Invalid datasource name");
61
+
62
+ expect(() =>
63
+ defineDatasource("my-datasource", {
64
+ schema: { id: t.string() },
65
+ })
66
+ ).toThrow("Invalid datasource name");
67
+
68
+ expect(() =>
69
+ defineDatasource("", {
70
+ schema: { id: t.string() },
71
+ })
72
+ ).toThrow("Invalid datasource name");
73
+ });
74
+
75
+ it("allows valid naming patterns", () => {
76
+ // Underscore prefix
77
+ const ds1 = defineDatasource("_private", {
78
+ schema: { id: t.string() },
79
+ });
80
+ expect(ds1._name).toBe("_private");
81
+
82
+ // With numbers
83
+ const ds2 = defineDatasource("events_v2", {
84
+ schema: { id: t.string() },
85
+ });
86
+ expect(ds2._name).toBe("events_v2");
87
+ });
88
+ });
89
+
90
+ describe("isDatasourceDefinition", () => {
91
+ it("returns true for valid datasource", () => {
92
+ const ds = defineDatasource("events", {
93
+ schema: { id: t.string() },
94
+ });
95
+
96
+ expect(isDatasourceDefinition(ds)).toBe(true);
97
+ });
98
+
99
+ it("returns false for non-datasource objects", () => {
100
+ expect(isDatasourceDefinition({})).toBe(false);
101
+ expect(isDatasourceDefinition(null)).toBe(false);
102
+ expect(isDatasourceDefinition(undefined)).toBe(false);
103
+ expect(isDatasourceDefinition("string")).toBe(false);
104
+ expect(isDatasourceDefinition(123)).toBe(false);
105
+ expect(isDatasourceDefinition({ _name: "test" })).toBe(false);
106
+ });
107
+ });
108
+
109
+ describe("getColumnType", () => {
110
+ it("returns type from raw validator", () => {
111
+ const validator = t.string();
112
+ const result = getColumnType(validator);
113
+
114
+ expect(result).toBe(validator);
115
+ });
116
+
117
+ it("returns type from column definition", () => {
118
+ const validator = t.string();
119
+ const col = column(validator, { jsonPath: "$.id" });
120
+ const result = getColumnType(col);
121
+
122
+ expect(result).toBe(validator);
123
+ });
124
+ });
125
+
126
+ describe("getColumnJsonPath", () => {
127
+ it("returns undefined for raw validator", () => {
128
+ const validator = t.string();
129
+ const result = getColumnJsonPath(validator);
130
+
131
+ expect(result).toBeUndefined();
132
+ });
133
+
134
+ it("returns jsonPath from column definition", () => {
135
+ const col = column(t.string(), { jsonPath: "$.user.id" });
136
+ const result = getColumnJsonPath(col);
137
+
138
+ expect(result).toBe("$.user.id");
139
+ });
140
+
141
+ it("returns undefined when jsonPath is not set", () => {
142
+ const col = column(t.string());
143
+ const result = getColumnJsonPath(col);
144
+
145
+ expect(result).toBeUndefined();
146
+ });
147
+ });
148
+
149
+ describe("getColumnNames", () => {
150
+ it("returns all column names from schema", () => {
151
+ const schema = {
152
+ id: t.string(),
153
+ timestamp: t.dateTime(),
154
+ user_id: t.string(),
155
+ };
156
+
157
+ const names = getColumnNames(schema);
158
+
159
+ expect(names).toHaveLength(3);
160
+ expect(names).toContain("id");
161
+ expect(names).toContain("timestamp");
162
+ expect(names).toContain("user_id");
163
+ });
164
+
165
+ it("returns empty array for empty schema", () => {
166
+ const names = getColumnNames({});
167
+
168
+ expect(names).toHaveLength(0);
169
+ });
170
+ });
171
+
172
+ describe("column", () => {
173
+ it("creates a column definition with type only", () => {
174
+ const col = column(t.string());
175
+
176
+ expect(col.type).toBeDefined();
177
+ expect(col.jsonPath).toBeUndefined();
178
+ });
179
+
180
+ it("creates a column definition with jsonPath", () => {
181
+ const col = column(t.string(), { jsonPath: "$.data.value" });
182
+
183
+ expect(col.type).toBeDefined();
184
+ expect(col.jsonPath).toBe("$.data.value");
185
+ });
186
+ });
187
+ });