@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
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Pipe content generator
3
+ * Converts PipeDefinition to native .pipe file format
4
+ */
5
+ import type { PipeDefinition } from "../schema/pipe.js";
6
+ /**
7
+ * Generated pipe content
8
+ */
9
+ export interface GeneratedPipe {
10
+ /** Pipe name */
11
+ name: string;
12
+ /** The generated .pipe file content */
13
+ content: string;
14
+ }
15
+ /**
16
+ * Generate a .pipe file content from a PipeDefinition
17
+ *
18
+ * @param pipe - The pipe definition
19
+ * @returns Generated pipe content
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const topEvents = definePipe('top_events', {
24
+ * description: 'Get top events by count',
25
+ * params: {
26
+ * start_date: p.dateTime(),
27
+ * limit: p.int32().optional(10),
28
+ * },
29
+ * nodes: [
30
+ * node({
31
+ * name: 'endpoint',
32
+ * sql: `
33
+ * SELECT event_type, count() as count
34
+ * FROM events
35
+ * WHERE timestamp >= {{DateTime(start_date)}}
36
+ * ORDER BY count DESC
37
+ * LIMIT {{Int32(limit, 10)}}
38
+ * `,
39
+ * }),
40
+ * ],
41
+ * output: {
42
+ * event_type: t.string(),
43
+ * count: t.uint64(),
44
+ * },
45
+ * endpoint: true,
46
+ * });
47
+ *
48
+ * const { content } = generatePipe(topEvents);
49
+ * // Returns:
50
+ * // DESCRIPTION >
51
+ * // Get top events by count
52
+ * //
53
+ * // NODE endpoint
54
+ * // SQL >
55
+ * // SELECT event_type, count() as count
56
+ * // FROM events
57
+ * // WHERE timestamp >= {{DateTime(start_date)}}
58
+ * // ORDER BY count DESC
59
+ * // LIMIT {{Int32(limit, 10)}}
60
+ * //
61
+ * // TYPE endpoint
62
+ * ```
63
+ */
64
+ export declare function generatePipe(pipe: PipeDefinition): GeneratedPipe;
65
+ /**
66
+ * Generate .pipe files for all pipes in a project
67
+ *
68
+ * @param pipes - Record of pipe definitions
69
+ * @returns Array of generated pipe content
70
+ */
71
+ export declare function generateAllPipes(pipes: Record<string, PipeDefinition>): GeneratedPipe[];
72
+ //# sourceMappingURL=pipe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipe.d.ts","sourceRoot":"","sources":["../../src/generator/pipe.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,cAAc,EAKf,MAAM,mBAAmB,CAAC;AAG3B;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;CACjB;AA6FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,aAAa,CA2ChE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GACpC,aAAa,EAAE,CAEjB"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Pipe content generator
3
+ * Converts PipeDefinition to native .pipe file format
4
+ */
5
+ import { getEndpointConfig, getMaterializedConfig, getCopyConfig } from "../schema/pipe.js";
6
+ /**
7
+ * Check if SQL contains template parameters like {{...}}
8
+ */
9
+ function hasDynamicParameters(sql) {
10
+ return /\{\{[^}]+\}\}/.test(sql);
11
+ }
12
+ /**
13
+ * Generate a NODE section for the pipe
14
+ */
15
+ function generateNode(node) {
16
+ const parts = [];
17
+ parts.push(`NODE ${node._name}`);
18
+ if (node.description) {
19
+ parts.push(`DESCRIPTION >`);
20
+ parts.push(` ${node.description}`);
21
+ }
22
+ parts.push(`SQL >`);
23
+ // Check if SQL has dynamic parameters - if so, add % on its own line
24
+ const isDynamic = hasDynamicParameters(node.sql);
25
+ if (isDynamic) {
26
+ parts.push(` %`);
27
+ }
28
+ const sqlLines = node.sql.trim().split("\n");
29
+ sqlLines.forEach((line) => {
30
+ parts.push(` ${line}`);
31
+ });
32
+ return parts.join("\n");
33
+ }
34
+ /**
35
+ * Generate the TYPE endpoint section
36
+ */
37
+ function generateEndpoint(endpoint) {
38
+ const parts = ["TYPE endpoint"];
39
+ if (endpoint.cache?.enabled) {
40
+ if (endpoint.cache.ttl !== undefined) {
41
+ parts.push(`CACHE ${endpoint.cache.ttl}`);
42
+ }
43
+ else {
44
+ parts.push("CACHE 60"); // Default cache TTL
45
+ }
46
+ }
47
+ return parts.join("\n");
48
+ }
49
+ /**
50
+ * Generate the TYPE MATERIALIZED section
51
+ */
52
+ function generateMaterialized(config) {
53
+ const parts = ["TYPE MATERIALIZED"];
54
+ // The config is normalized by definePipe to always have `datasource` set.
55
+ // Use non-null assertion since we know it's always present after normalization.
56
+ const datasourceName = config.datasource._name;
57
+ parts.push(`DATASOURCE ${datasourceName}`);
58
+ if (config.deploymentMethod === "alter") {
59
+ parts.push("DEPLOYMENT_METHOD alter");
60
+ }
61
+ return parts.join("\n");
62
+ }
63
+ /**
64
+ * Generate the TYPE COPY section
65
+ */
66
+ function generateCopy(config) {
67
+ const parts = ["TYPE COPY"];
68
+ const datasourceName = config.datasource._name;
69
+ parts.push(`TARGET_DATASOURCE ${datasourceName}`);
70
+ if (config.copy_schedule) {
71
+ parts.push(`COPY_SCHEDULE ${config.copy_schedule}`);
72
+ }
73
+ if (config.copy_mode) {
74
+ parts.push(`COPY_MODE ${config.copy_mode}`);
75
+ }
76
+ return parts.join("\n");
77
+ }
78
+ /**
79
+ * Generate a .pipe file content from a PipeDefinition
80
+ *
81
+ * @param pipe - The pipe definition
82
+ * @returns Generated pipe content
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * const topEvents = definePipe('top_events', {
87
+ * description: 'Get top events by count',
88
+ * params: {
89
+ * start_date: p.dateTime(),
90
+ * limit: p.int32().optional(10),
91
+ * },
92
+ * nodes: [
93
+ * node({
94
+ * name: 'endpoint',
95
+ * sql: `
96
+ * SELECT event_type, count() as count
97
+ * FROM events
98
+ * WHERE timestamp >= {{DateTime(start_date)}}
99
+ * ORDER BY count DESC
100
+ * LIMIT {{Int32(limit, 10)}}
101
+ * `,
102
+ * }),
103
+ * ],
104
+ * output: {
105
+ * event_type: t.string(),
106
+ * count: t.uint64(),
107
+ * },
108
+ * endpoint: true,
109
+ * });
110
+ *
111
+ * const { content } = generatePipe(topEvents);
112
+ * // Returns:
113
+ * // DESCRIPTION >
114
+ * // Get top events by count
115
+ * //
116
+ * // NODE endpoint
117
+ * // SQL >
118
+ * // SELECT event_type, count() as count
119
+ * // FROM events
120
+ * // WHERE timestamp >= {{DateTime(start_date)}}
121
+ * // ORDER BY count DESC
122
+ * // LIMIT {{Int32(limit, 10)}}
123
+ * //
124
+ * // TYPE endpoint
125
+ * ```
126
+ */
127
+ export function generatePipe(pipe) {
128
+ const parts = [];
129
+ // Add description if present
130
+ if (pipe.options.description) {
131
+ parts.push(`DESCRIPTION >\n ${pipe.options.description}`);
132
+ parts.push("");
133
+ }
134
+ // Add all nodes
135
+ pipe.options.nodes.forEach((node, index) => {
136
+ parts.push(generateNode(node));
137
+ // Add empty line between nodes
138
+ if (index < pipe.options.nodes.length - 1) {
139
+ parts.push("");
140
+ }
141
+ });
142
+ // Add endpoint configuration if this is an endpoint
143
+ const endpointConfig = getEndpointConfig(pipe);
144
+ if (endpointConfig) {
145
+ parts.push("");
146
+ parts.push(generateEndpoint(endpointConfig));
147
+ }
148
+ // Add materialized view configuration if this is a materialized view
149
+ const materializedConfig = getMaterializedConfig(pipe);
150
+ if (materializedConfig) {
151
+ parts.push("");
152
+ parts.push(generateMaterialized(materializedConfig));
153
+ }
154
+ // Add copy pipe configuration if this is a copy pipe
155
+ const copyConfig = getCopyConfig(pipe);
156
+ if (copyConfig) {
157
+ parts.push("");
158
+ parts.push(generateCopy(copyConfig));
159
+ }
160
+ return {
161
+ name: pipe._name,
162
+ content: parts.join("\n"),
163
+ };
164
+ }
165
+ /**
166
+ * Generate .pipe files for all pipes in a project
167
+ *
168
+ * @param pipes - Record of pipe definitions
169
+ * @returns Array of generated pipe content
170
+ */
171
+ export function generateAllPipes(pipes) {
172
+ return Object.values(pipes).map(generatePipe);
173
+ }
174
+ //# sourceMappingURL=pipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipe.js","sourceRoot":"","sources":["../../src/generator/pipe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pipe.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipe.test.d.ts","sourceRoot":"","sources":["../../src/generator/pipe.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,393 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { generatePipe, generateAllPipes } from './pipe.js';
3
+ import { definePipe, defineMaterializedView, node } from '../schema/pipe.js';
4
+ import { defineDatasource } from '../schema/datasource.js';
5
+ import { t } from '../schema/types.js';
6
+ import { p } from '../schema/params.js';
7
+ import { engine } from '../schema/engines.js';
8
+ // Helper to create a simple output schema for tests
9
+ const simpleOutput = { result: t.int32() };
10
+ describe('Pipe Generator', () => {
11
+ describe('generatePipe', () => {
12
+ it('generates basic pipe with node', () => {
13
+ const pipe = definePipe('test_pipe', {
14
+ nodes: [
15
+ node({
16
+ name: 'endpoint',
17
+ sql: 'SELECT * FROM table',
18
+ }),
19
+ ],
20
+ output: simpleOutput,
21
+ endpoint: true,
22
+ });
23
+ const result = generatePipe(pipe);
24
+ expect(result.name).toBe('test_pipe');
25
+ expect(result.content).toContain('NODE endpoint');
26
+ expect(result.content).toContain('SQL >');
27
+ expect(result.content).toContain('SELECT * FROM table');
28
+ });
29
+ it('includes description when provided', () => {
30
+ const pipe = definePipe('test_pipe', {
31
+ description: 'Test pipe description',
32
+ nodes: [node({ name: 'endpoint', sql: 'SELECT 1' })],
33
+ output: simpleOutput,
34
+ endpoint: true,
35
+ });
36
+ const result = generatePipe(pipe);
37
+ expect(result.content).toContain('DESCRIPTION >');
38
+ expect(result.content).toContain('Test pipe description');
39
+ });
40
+ it('includes TYPE endpoint when endpoint is true', () => {
41
+ const pipe = definePipe('test_pipe', {
42
+ nodes: [node({ name: 'endpoint', sql: 'SELECT 1' })],
43
+ output: simpleOutput,
44
+ endpoint: true,
45
+ });
46
+ const result = generatePipe(pipe);
47
+ expect(result.content).toContain('TYPE endpoint');
48
+ });
49
+ it('does not include TYPE endpoint when endpoint is false', () => {
50
+ const pipe = definePipe('test_pipe', {
51
+ nodes: [node({ name: 'endpoint', sql: 'SELECT 1' })],
52
+ output: simpleOutput,
53
+ endpoint: false,
54
+ });
55
+ const result = generatePipe(pipe);
56
+ expect(result.content).not.toContain('TYPE endpoint');
57
+ });
58
+ });
59
+ describe('Dynamic SQL detection', () => {
60
+ it('adds % on its own line for SQL with template parameters', () => {
61
+ const pipe = definePipe('test_pipe', {
62
+ nodes: [
63
+ node({
64
+ name: 'endpoint',
65
+ sql: 'SELECT * FROM table WHERE id = {{Int32(id)}}',
66
+ }),
67
+ ],
68
+ output: simpleOutput,
69
+ endpoint: true,
70
+ });
71
+ const result = generatePipe(pipe);
72
+ expect(result.content).toContain('SQL >\n %\n SELECT');
73
+ });
74
+ it('adds % for SQL with DateTime parameter', () => {
75
+ const pipe = definePipe('test_pipe', {
76
+ nodes: [
77
+ node({
78
+ name: 'endpoint',
79
+ sql: 'SELECT * FROM table WHERE timestamp >= {{DateTime(start_date)}}',
80
+ }),
81
+ ],
82
+ output: simpleOutput,
83
+ endpoint: true,
84
+ });
85
+ const result = generatePipe(pipe);
86
+ expect(result.content).toContain(' %\n');
87
+ });
88
+ it('does not add % for SQL without template parameters', () => {
89
+ const pipe = definePipe('test_pipe', {
90
+ nodes: [
91
+ node({
92
+ name: 'endpoint',
93
+ sql: 'SELECT * FROM table',
94
+ }),
95
+ ],
96
+ output: simpleOutput,
97
+ endpoint: true,
98
+ });
99
+ const result = generatePipe(pipe);
100
+ expect(result.content).not.toContain('%');
101
+ });
102
+ it('does not add % for SQL with curly braces that are not parameters', () => {
103
+ const pipe = definePipe('test_pipe', {
104
+ nodes: [
105
+ node({
106
+ name: 'endpoint',
107
+ sql: "SELECT JSONExtract(data, 'field', 'String') FROM table",
108
+ }),
109
+ ],
110
+ output: simpleOutput,
111
+ endpoint: true,
112
+ });
113
+ const result = generatePipe(pipe);
114
+ expect(result.content).not.toContain('%');
115
+ });
116
+ });
117
+ describe('Multiple nodes', () => {
118
+ it('generates all nodes with separation', () => {
119
+ const pipe = definePipe('test_pipe', {
120
+ nodes: [
121
+ node({ name: 'first', sql: 'SELECT * FROM table1' }),
122
+ node({ name: 'second', sql: 'SELECT * FROM first' }),
123
+ ],
124
+ output: simpleOutput,
125
+ endpoint: true,
126
+ });
127
+ const result = generatePipe(pipe);
128
+ expect(result.content).toContain('NODE first');
129
+ expect(result.content).toContain('NODE second');
130
+ expect(result.content).toContain('SELECT * FROM table1');
131
+ expect(result.content).toContain('SELECT * FROM first');
132
+ });
133
+ it('includes node descriptions', () => {
134
+ const pipe = definePipe('test_pipe', {
135
+ nodes: [
136
+ node({
137
+ name: 'endpoint',
138
+ description: 'This is a test node',
139
+ sql: 'SELECT 1',
140
+ }),
141
+ ],
142
+ output: simpleOutput,
143
+ endpoint: true,
144
+ });
145
+ const result = generatePipe(pipe);
146
+ expect(result.content).toContain('NODE endpoint');
147
+ expect(result.content).toContain('DESCRIPTION >');
148
+ expect(result.content).toContain('This is a test node');
149
+ });
150
+ });
151
+ describe('Endpoint configuration', () => {
152
+ it('includes cache when enabled', () => {
153
+ const pipe = definePipe('test_pipe', {
154
+ nodes: [node({ name: 'endpoint', sql: 'SELECT 1' })],
155
+ output: simpleOutput,
156
+ endpoint: {
157
+ enabled: true,
158
+ cache: { enabled: true, ttl: 300 },
159
+ },
160
+ });
161
+ const result = generatePipe(pipe);
162
+ expect(result.content).toContain('TYPE endpoint');
163
+ expect(result.content).toContain('CACHE 300');
164
+ });
165
+ it('uses default cache TTL when not specified', () => {
166
+ const pipe = definePipe('test_pipe', {
167
+ nodes: [node({ name: 'endpoint', sql: 'SELECT 1' })],
168
+ output: simpleOutput,
169
+ endpoint: {
170
+ enabled: true,
171
+ cache: { enabled: true },
172
+ },
173
+ });
174
+ const result = generatePipe(pipe);
175
+ expect(result.content).toContain('CACHE 60');
176
+ });
177
+ });
178
+ describe('generateAllPipes', () => {
179
+ it('generates all pipes', () => {
180
+ const pipe1 = definePipe('pipe1', {
181
+ nodes: [node({ name: 'endpoint', sql: 'SELECT 1' })],
182
+ output: simpleOutput,
183
+ endpoint: true,
184
+ });
185
+ const pipe2 = definePipe('pipe2', {
186
+ nodes: [node({ name: 'endpoint', sql: 'SELECT 2' })],
187
+ output: simpleOutput,
188
+ endpoint: true,
189
+ });
190
+ const results = generateAllPipes({ pipe1, pipe2 });
191
+ expect(results).toHaveLength(2);
192
+ expect(results.map(r => r.name).sort()).toEqual(['pipe1', 'pipe2']);
193
+ });
194
+ });
195
+ describe('Full integration', () => {
196
+ it('generates complete pipe file', () => {
197
+ const pipe = definePipe('top_pages', {
198
+ description: 'Get the most visited pages',
199
+ params: {
200
+ start_date: p.dateTime(),
201
+ end_date: p.dateTime(),
202
+ limit: p.int32().optional(10),
203
+ },
204
+ nodes: [
205
+ node({
206
+ name: 'aggregated',
207
+ sql: `
208
+ SELECT
209
+ pathname,
210
+ count() AS views
211
+ FROM page_views
212
+ WHERE timestamp >= {{DateTime(start_date)}}
213
+ AND timestamp <= {{DateTime(end_date)}}
214
+ GROUP BY pathname
215
+ ORDER BY views DESC
216
+ LIMIT {{Int32(limit, 10)}}
217
+ `.trim(),
218
+ }),
219
+ ],
220
+ output: {
221
+ pathname: t.string(),
222
+ views: t.uint64(),
223
+ },
224
+ endpoint: true,
225
+ });
226
+ const result = generatePipe(pipe);
227
+ expect(result.name).toBe('top_pages');
228
+ expect(result.content).toContain('DESCRIPTION >');
229
+ expect(result.content).toContain('Get the most visited pages');
230
+ expect(result.content).toContain('NODE aggregated');
231
+ expect(result.content).toContain('SQL >');
232
+ expect(result.content).toContain(' %\n');
233
+ expect(result.content).toContain('pathname');
234
+ expect(result.content).toContain('{{DateTime(start_date)}}');
235
+ expect(result.content).toContain('{{Int32(limit, 10)}}');
236
+ expect(result.content).toContain('TYPE endpoint');
237
+ });
238
+ });
239
+ describe('Materialized Views', () => {
240
+ const salesByHour = defineDatasource('sales_by_hour', {
241
+ schema: {
242
+ day: t.date(),
243
+ country: t.string().lowCardinality(),
244
+ total_sales: t.simpleAggregateFunction('sum', t.uint64()),
245
+ },
246
+ engine: engine.aggregatingMergeTree({
247
+ sortingKey: ['day', 'country'],
248
+ }),
249
+ });
250
+ it('generates TYPE MATERIALIZED and DATASOURCE with datasource', () => {
251
+ const pipe = definePipe('sales_by_hour_mv', {
252
+ nodes: [
253
+ node({
254
+ name: 'daily_sales',
255
+ sql: 'SELECT toStartOfDay(date) as day, country, sum(sales) as total_sales FROM teams GROUP BY day, country',
256
+ }),
257
+ ],
258
+ output: {
259
+ day: t.date(),
260
+ country: t.string().lowCardinality(),
261
+ total_sales: t.simpleAggregateFunction('sum', t.uint64()),
262
+ },
263
+ materialized: {
264
+ datasource: salesByHour,
265
+ },
266
+ });
267
+ const result = generatePipe(pipe);
268
+ expect(result.content).toContain('TYPE MATERIALIZED');
269
+ expect(result.content).toContain('DATASOURCE sales_by_hour');
270
+ expect(result.content).not.toContain('TYPE endpoint');
271
+ });
272
+ it('generates DEPLOYMENT_METHOD alter when specified', () => {
273
+ const pipe = definePipe('sales_by_hour_mv', {
274
+ nodes: [
275
+ node({
276
+ name: 'daily_sales',
277
+ sql: 'SELECT toStartOfDay(date) as day, country, sum(sales) as total_sales FROM teams GROUP BY day, country',
278
+ }),
279
+ ],
280
+ output: {
281
+ day: t.date(),
282
+ country: t.string().lowCardinality(),
283
+ total_sales: t.simpleAggregateFunction('sum', t.uint64()),
284
+ },
285
+ materialized: {
286
+ datasource: salesByHour,
287
+ deploymentMethod: 'alter',
288
+ },
289
+ });
290
+ const result = generatePipe(pipe);
291
+ expect(result.content).toContain('TYPE MATERIALIZED');
292
+ expect(result.content).toContain('DATASOURCE sales_by_hour');
293
+ expect(result.content).toContain('DEPLOYMENT_METHOD alter');
294
+ });
295
+ it('does not include DEPLOYMENT_METHOD when not specified', () => {
296
+ const pipe = definePipe('sales_by_hour_mv', {
297
+ nodes: [
298
+ node({
299
+ name: 'daily_sales',
300
+ sql: 'SELECT toStartOfDay(date) as day, country, sum(sales) as total_sales FROM teams GROUP BY day, country',
301
+ }),
302
+ ],
303
+ output: {
304
+ day: t.date(),
305
+ country: t.string().lowCardinality(),
306
+ total_sales: t.simpleAggregateFunction('sum', t.uint64()),
307
+ },
308
+ materialized: {
309
+ datasource: salesByHour,
310
+ },
311
+ });
312
+ const result = generatePipe(pipe);
313
+ expect(result.content).not.toContain('DEPLOYMENT_METHOD');
314
+ });
315
+ it('generates complete materialized view pipe file', () => {
316
+ const pipe = definePipe('sales_by_hour_mv', {
317
+ description: 'Aggregate sales per hour',
318
+ nodes: [
319
+ node({
320
+ name: 'daily_sales',
321
+ sql: `
322
+ SELECT
323
+ toStartOfDay(starting_date) as day,
324
+ country,
325
+ sum(sales) as total_sales
326
+ FROM teams
327
+ GROUP BY day, country
328
+ `.trim(),
329
+ }),
330
+ ],
331
+ output: {
332
+ day: t.date(),
333
+ country: t.string().lowCardinality(),
334
+ total_sales: t.simpleAggregateFunction('sum', t.uint64()),
335
+ },
336
+ materialized: {
337
+ datasource: salesByHour,
338
+ deploymentMethod: 'alter',
339
+ },
340
+ });
341
+ const result = generatePipe(pipe);
342
+ expect(result.name).toBe('sales_by_hour_mv');
343
+ expect(result.content).toContain('DESCRIPTION >');
344
+ expect(result.content).toContain('Aggregate sales per hour');
345
+ expect(result.content).toContain('NODE daily_sales');
346
+ expect(result.content).toContain('SQL >');
347
+ expect(result.content).toContain('toStartOfDay(starting_date) as day');
348
+ expect(result.content).toContain('TYPE MATERIALIZED');
349
+ expect(result.content).toContain('DATASOURCE sales_by_hour');
350
+ expect(result.content).toContain('DEPLOYMENT_METHOD alter');
351
+ });
352
+ it('works with defineMaterializedView helper using datasource', () => {
353
+ const pipe = defineMaterializedView('sales_mv', {
354
+ description: 'Sales materialized view',
355
+ datasource: salesByHour,
356
+ nodes: [
357
+ node({
358
+ name: 'daily_sales',
359
+ sql: 'SELECT toStartOfDay(date) as day, country, sum(sales) as total_sales FROM events GROUP BY day, country',
360
+ }),
361
+ ],
362
+ deploymentMethod: 'alter',
363
+ });
364
+ const result = generatePipe(pipe);
365
+ expect(result.name).toBe('sales_mv');
366
+ expect(result.content).toContain('TYPE MATERIALIZED');
367
+ expect(result.content).toContain('DATASOURCE sales_by_hour');
368
+ expect(result.content).toContain('DEPLOYMENT_METHOD alter');
369
+ });
370
+ it('generates DATASOURCE correctly with datasource field', () => {
371
+ const pipe = definePipe('sales_by_hour_mv_2', {
372
+ nodes: [
373
+ node({
374
+ name: 'daily_sales',
375
+ sql: 'SELECT toStartOfDay(date) as day, country, sum(sales) as total_sales FROM teams GROUP BY day, country',
376
+ }),
377
+ ],
378
+ output: {
379
+ day: t.date(),
380
+ country: t.string().lowCardinality(),
381
+ total_sales: t.simpleAggregateFunction('sum', t.uint64()),
382
+ },
383
+ materialized: {
384
+ datasource: salesByHour,
385
+ },
386
+ });
387
+ const result = generatePipe(pipe);
388
+ expect(result.content).toContain('TYPE MATERIALIZED');
389
+ expect(result.content).toContain('DATASOURCE sales_by_hour');
390
+ });
391
+ });
392
+ });
393
+ //# sourceMappingURL=pipe.test.js.map