@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,175 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import { generateResources, build } from "./index.js";
3
+ import { defineProject } from "../schema/project.js";
4
+ import { defineDatasource } from "../schema/datasource.js";
5
+ import { definePipe, node } from "../schema/pipe.js";
6
+ import { t } from "../schema/types.js";
7
+ import { engine } from "../schema/engines.js";
8
+ import * as fs from "fs";
9
+ import * as path from "path";
10
+ import * as os from "os";
11
+ describe("Generator Index", () => {
12
+ describe("generateResources", () => {
13
+ it("generates resources from a project definition", () => {
14
+ const events = defineDatasource("events", {
15
+ schema: {
16
+ timestamp: t.dateTime(),
17
+ event_name: t.string(),
18
+ },
19
+ });
20
+ const topEvents = definePipe("top_events", {
21
+ nodes: [
22
+ node({
23
+ name: "endpoint",
24
+ sql: "SELECT event_name, count() as cnt FROM events GROUP BY event_name",
25
+ }),
26
+ ],
27
+ output: {
28
+ event_name: t.string(),
29
+ cnt: t.uint64(),
30
+ },
31
+ endpoint: true,
32
+ });
33
+ const project = defineProject({
34
+ datasources: { events },
35
+ pipes: { topEvents },
36
+ });
37
+ const result = generateResources(project);
38
+ expect(result.datasources).toHaveLength(1);
39
+ expect(result.datasources[0].name).toBe("events");
40
+ expect(result.datasources[0].content).toContain("timestamp DateTime");
41
+ expect(result.pipes).toHaveLength(1);
42
+ expect(result.pipes[0].name).toBe("top_events");
43
+ expect(result.pipes[0].content).toContain("SELECT event_name");
44
+ });
45
+ it("handles empty project", () => {
46
+ const project = defineProject({
47
+ datasources: {},
48
+ pipes: {},
49
+ });
50
+ const result = generateResources(project);
51
+ expect(result.datasources).toHaveLength(0);
52
+ expect(result.pipes).toHaveLength(0);
53
+ });
54
+ it("generates multiple datasources and pipes", () => {
55
+ const ds1 = defineDatasource("ds1", { schema: { id: t.string() } });
56
+ const ds2 = defineDatasource("ds2", { schema: { name: t.string() } });
57
+ const ds3 = defineDatasource("ds3", { schema: { count: t.int32() } });
58
+ const pipe1 = definePipe("pipe1", {
59
+ nodes: [node({ name: "n", sql: "SELECT * FROM ds1" })],
60
+ output: { id: t.string() },
61
+ endpoint: true,
62
+ });
63
+ const pipe2 = definePipe("pipe2", {
64
+ nodes: [node({ name: "n", sql: "SELECT * FROM ds2" })],
65
+ output: { name: t.string() },
66
+ endpoint: true,
67
+ });
68
+ const project = defineProject({
69
+ datasources: { ds1, ds2, ds3 },
70
+ pipes: { pipe1, pipe2 },
71
+ });
72
+ const result = generateResources(project);
73
+ expect(result.datasources).toHaveLength(3);
74
+ expect(result.pipes).toHaveLength(2);
75
+ });
76
+ it("generates datasources with full options", () => {
77
+ const events = defineDatasource("events", {
78
+ description: "Event tracking data",
79
+ schema: {
80
+ timestamp: t.dateTime(),
81
+ event_name: t.string(),
82
+ user_id: t.string().nullable(),
83
+ metadata: t.string().default("{}"),
84
+ },
85
+ engine: engine.mergeTree({
86
+ sortingKey: ["timestamp", "event_name"],
87
+ partitionKey: "toYYYYMM(timestamp)",
88
+ }),
89
+ });
90
+ const project = defineProject({
91
+ datasources: { events },
92
+ pipes: {},
93
+ });
94
+ const result = generateResources(project);
95
+ expect(result.datasources).toHaveLength(1);
96
+ expect(result.datasources[0].content).toContain("DESCRIPTION >");
97
+ expect(result.datasources[0].content).toContain("Event tracking data");
98
+ expect(result.datasources[0].content).toContain("ENGINE_SORTING_KEY");
99
+ expect(result.datasources[0].content).toContain("ENGINE_PARTITION_KEY");
100
+ });
101
+ it("generates pipes with endpoint config", () => {
102
+ const stats = definePipe("stats", {
103
+ description: "Get stats",
104
+ nodes: [
105
+ node({
106
+ name: "calc",
107
+ description: "Calculate statistics",
108
+ sql: "SELECT count() as total FROM events",
109
+ }),
110
+ ],
111
+ output: { total: t.uint64() },
112
+ endpoint: {
113
+ enabled: true,
114
+ cache: { enabled: true, ttl: 120 },
115
+ },
116
+ });
117
+ const project = defineProject({
118
+ datasources: {},
119
+ pipes: { stats },
120
+ });
121
+ const result = generateResources(project);
122
+ expect(result.pipes).toHaveLength(1);
123
+ expect(result.pipes[0].content).toContain("DESCRIPTION >");
124
+ expect(result.pipes[0].content).toContain("Get stats");
125
+ expect(result.pipes[0].content).toContain("TYPE endpoint");
126
+ expect(result.pipes[0].content).toContain("CACHE 120");
127
+ });
128
+ it("generates non-endpoint pipes", () => {
129
+ const materialize = definePipe("materialize", {
130
+ nodes: [
131
+ node({
132
+ name: "aggregate",
133
+ sql: "SELECT event_name, count() FROM events GROUP BY event_name",
134
+ }),
135
+ ],
136
+ output: { event_name: t.string() },
137
+ endpoint: false,
138
+ });
139
+ const project = defineProject({
140
+ datasources: {},
141
+ pipes: { materialize },
142
+ });
143
+ const result = generateResources(project);
144
+ expect(result.pipes).toHaveLength(1);
145
+ expect(result.pipes[0].content).not.toContain("TYPE endpoint");
146
+ });
147
+ });
148
+ describe("build", () => {
149
+ let tempDir;
150
+ beforeEach(() => {
151
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "tinybird-test-"));
152
+ });
153
+ afterEach(() => {
154
+ try {
155
+ fs.rmSync(tempDir, { recursive: true });
156
+ }
157
+ catch {
158
+ // Ignore cleanup errors
159
+ }
160
+ });
161
+ it("throws error for non-existent schema file", async () => {
162
+ const schemaPath = path.join(tempDir, "nonexistent.ts");
163
+ await expect(build({ schemaPath })).rejects.toThrow("Schema file not found");
164
+ });
165
+ it("throws error when no project definition is exported", async () => {
166
+ const schemaContent = `
167
+ export const notAProject = { foo: "bar" };
168
+ `;
169
+ const schemaPath = path.join(tempDir, "invalid-schema.ts");
170
+ fs.writeFileSync(schemaPath, schemaContent);
171
+ await expect(build({ schemaPath })).rejects.toThrow("No ProjectDefinition found");
172
+ });
173
+ });
174
+ });
175
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/generator/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;YACvD,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE;gBACxC,MAAM,EAAE;oBACN,SAAS,EAAE,CAAC,CAAC,QAAQ,EAAE;oBACvB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;iBACvB;aACF,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE;gBACzC,KAAK,EAAE;oBACL,IAAI,CAAC;wBACH,IAAI,EAAE,UAAU;wBAChB,GAAG,EAAE,mEAAmE;qBACzE,CAAC;iBACH;gBACD,MAAM,EAAE;oBACN,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;oBACtB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;iBAChB;gBACD,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,aAAa,CAAC;gBAC5B,WAAW,EAAE,EAAE,MAAM,EAAE;gBACvB,KAAK,EAAE,EAAE,SAAS,EAAE;aACrB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAE1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YAEtE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAChD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;YAC/B,MAAM,OAAO,GAAG,aAAa,CAAC;gBAC5B,WAAW,EAAE,EAAE;gBACf,KAAK,EAAE,EAAE;aACV,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAE1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;YACpE,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;YACtE,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;YAEtE,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE;gBAChC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBACtD,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;gBAC1B,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC;YACH,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE;gBAChC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,mBAAmB,EAAE,CAAC,CAAC;gBACtD,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;gBAC5B,QAAQ,EAAE,IAAI;aACf,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,aAAa,CAAC;gBAC5B,WAAW,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;gBAC9B,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;aACxB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAE1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE;gBACxC,WAAW,EAAE,qBAAqB;gBAClC,MAAM,EAAE;oBACN,SAAS,EAAE,CAAC,CAAC,QAAQ,EAAE;oBACvB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;oBACtB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;oBAC9B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;iBACnC;gBACD,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC;oBACvB,UAAU,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC;oBACvC,YAAY,EAAE,qBAAqB;iBACpC,CAAC;aACH,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,aAAa,CAAC;gBAC5B,WAAW,EAAE,EAAE,MAAM,EAAE;gBACvB,KAAK,EAAE,EAAE;aACV,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAE1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YACjE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;YACvE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;YACtE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE;gBAChC,WAAW,EAAE,WAAW;gBACxB,KAAK,EAAE;oBACL,IAAI,CAAC;wBACH,IAAI,EAAE,MAAM;wBACZ,WAAW,EAAE,sBAAsB;wBACnC,GAAG,EAAE,qCAAqC;qBAC3C,CAAC;iBACH;gBACD,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;gBAC7B,QAAQ,EAAE;oBACR,OAAO,EAAE,IAAI;oBACb,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE;iBACnC;aACF,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,aAAa,CAAC;gBAC5B,WAAW,EAAE,EAAE;gBACf,KAAK,EAAE,EAAE,KAAK,EAAE;aACjB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAE1C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YAC3D,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;YACvD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YAC3D,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,WAAW,GAAG,UAAU,CAAC,aAAa,EAAE;gBAC5C,KAAK,EAAE;oBACL,IAAI,CAAC;wBACH,IAAI,EAAE,WAAW;wBACjB,GAAG,EAAE,4DAA4D;qBAClE,CAAC;iBACH;gBACD,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;gBAClC,QAAQ,EAAE,KAAK;aAChB,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,aAAa,CAAC;gBAC5B,WAAW,EAAE,EAAE;gBACf,KAAK,EAAE,EAAE,WAAW,EAAE;aACvB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAE1C,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;QACrB,IAAI,OAAe,CAAC;QAEpB,UAAU,CAAC,GAAG,EAAE;YACd,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,IAAI,CAAC;gBACH,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;YAExD,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QAC/E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,aAAa,GAAG;;CAE3B,CAAC;YAEI,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;YAC3D,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;YAE5C,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACjD,4BAA4B,CAC7B,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Schema loader using esbuild
3
+ * Bundles and executes TypeScript schema files at runtime
4
+ */
5
+ import { type ProjectDefinition, type DatasourcesDefinition, type PipesDefinition } from "../schema/project.js";
6
+ import { type DatasourceDefinition } from "../schema/datasource.js";
7
+ import { type PipeDefinition } from "../schema/pipe.js";
8
+ /**
9
+ * Result of loading a schema file
10
+ */
11
+ export interface LoadedSchema {
12
+ /** The loaded project definition */
13
+ project: ProjectDefinition;
14
+ /** The resolved path to the schema file */
15
+ schemaPath: string;
16
+ /** The directory containing the schema */
17
+ schemaDir: string;
18
+ }
19
+ /**
20
+ * Options for the schema loader
21
+ */
22
+ export interface LoaderOptions {
23
+ /** The path to the schema file (can be relative or absolute) */
24
+ schemaPath: string;
25
+ /** The working directory for resolution (defaults to cwd) */
26
+ cwd?: string;
27
+ }
28
+ /**
29
+ * Load and execute a TypeScript schema file
30
+ *
31
+ * Uses esbuild to bundle the schema and its dependencies,
32
+ * then dynamically imports the bundle to get the ProjectDefinition.
33
+ *
34
+ * @param options - Loader options
35
+ * @returns The loaded project definition
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const { project } = await loadSchema({
40
+ * schemaPath: 'src/tinybird/schema.ts',
41
+ * });
42
+ *
43
+ * console.log(project.datasources);
44
+ * console.log(project.pipes);
45
+ * ```
46
+ */
47
+ export declare function loadSchema(options: LoaderOptions): Promise<LoadedSchema>;
48
+ /**
49
+ * Information about an entity discovered from a source file
50
+ */
51
+ export interface EntityInfo {
52
+ /** The export name used in the source file */
53
+ exportName: string;
54
+ /** The source file path (relative to cwd) */
55
+ sourceFile: string;
56
+ }
57
+ /**
58
+ * Result of loading entities from multiple files
59
+ */
60
+ export interface LoadedEntities {
61
+ /** Discovered datasources with their metadata */
62
+ datasources: Record<string, {
63
+ definition: DatasourceDefinition;
64
+ info: EntityInfo;
65
+ }>;
66
+ /** Discovered pipes with their metadata */
67
+ pipes: Record<string, {
68
+ definition: PipeDefinition;
69
+ info: EntityInfo;
70
+ }>;
71
+ /** All source files that were scanned */
72
+ sourceFiles: string[];
73
+ }
74
+ /**
75
+ * Options for loading entities
76
+ */
77
+ export interface LoadEntitiesOptions {
78
+ /** Array of file paths to scan (can be relative or absolute) */
79
+ includePaths: string[];
80
+ /** The working directory for resolution (defaults to cwd) */
81
+ cwd?: string;
82
+ }
83
+ /**
84
+ * Load datasources and pipes from multiple TypeScript files
85
+ *
86
+ * Uses esbuild to bundle each file and scans exports for datasource
87
+ * and pipe definitions.
88
+ *
89
+ * @param options - Loader options
90
+ * @returns Discovered entities with metadata
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * const entities = await loadEntities({
95
+ * includePaths: ['src/datasources.ts', 'src/pipes.ts'],
96
+ * });
97
+ *
98
+ * console.log(Object.keys(entities.datasources)); // ['pageViews', 'events']
99
+ * console.log(Object.keys(entities.pipes)); // ['topPages', 'topEvents']
100
+ * ```
101
+ */
102
+ export declare function loadEntities(options: LoadEntitiesOptions): Promise<LoadedEntities>;
103
+ /**
104
+ * Convert loaded entities to a format compatible with generators
105
+ */
106
+ export declare function entitiesToProject(entities: LoadedEntities): {
107
+ datasources: DatasourcesDefinition;
108
+ pipes: PipesDefinition;
109
+ };
110
+ /**
111
+ * Watch options for the schema loader
112
+ */
113
+ export interface WatchOptions extends LoaderOptions {
114
+ /** Callback when the schema changes */
115
+ onChange: (result: LoadedSchema) => void | Promise<void>;
116
+ /** Callback when there's an error loading the schema */
117
+ onError?: (error: Error) => void;
118
+ /** Debounce delay in milliseconds (default: 100) */
119
+ debounce?: number;
120
+ }
121
+ /**
122
+ * Schema watcher controller
123
+ */
124
+ export interface SchemaWatcher {
125
+ /** Stop watching for changes */
126
+ close: () => Promise<void>;
127
+ /** The initial loaded schema */
128
+ initialSchema: LoadedSchema;
129
+ }
130
+ /**
131
+ * Watch a TypeScript schema file for changes
132
+ *
133
+ * Performs an initial load, then watches for file changes and reloads.
134
+ * Uses debouncing to coalesce rapid file system events.
135
+ *
136
+ * @param options - Watch options
137
+ * @returns A controller to stop watching
138
+ *
139
+ * @example
140
+ * ```ts
141
+ * const watcher = await watchSchema({
142
+ * schemaPath: 'src/tinybird/schema.ts',
143
+ * onChange: (schema) => {
144
+ * console.log('Schema updated:', schema.project);
145
+ * },
146
+ * onError: (err) => {
147
+ * console.error('Load error:', err.message);
148
+ * },
149
+ * });
150
+ *
151
+ * // Later, stop watching
152
+ * await watcher.close();
153
+ * ```
154
+ */
155
+ export declare function watchSchema(options: WatchOptions): Promise<SchemaWatcher>;
156
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/generator/loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAuB,KAAK,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACrI,OAAO,EAA0B,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAqF9E;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,oBAAoB,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IACpF,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,cAAc,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;IACxE,yCAAyC;IACzC,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,6DAA6D;IAC7D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC,CAoFxF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG;IAC3D,WAAW,EAAE,qBAAqB,CAAC;IACnC,KAAK,EAAE,eAAe,CAAC;CACxB,CAaA;AAED;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD,uCAAuC;IACvC,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,wDAAwD;IACxD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,gCAAgC;IAChC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,gCAAgC;IAChC,aAAa,EAAE,YAAY,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CA2D/E"}
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Schema loader using esbuild
3
+ * Bundles and executes TypeScript schema files at runtime
4
+ */
5
+ import * as esbuild from "esbuild";
6
+ import * as path from "path";
7
+ import * as fs from "fs";
8
+ import { watch as chokidarWatch } from "chokidar";
9
+ import { isProjectDefinition } from "../schema/project.js";
10
+ import { isDatasourceDefinition } from "../schema/datasource.js";
11
+ import { isPipeDefinition } from "../schema/pipe.js";
12
+ /**
13
+ * Load and execute a TypeScript schema file
14
+ *
15
+ * Uses esbuild to bundle the schema and its dependencies,
16
+ * then dynamically imports the bundle to get the ProjectDefinition.
17
+ *
18
+ * @param options - Loader options
19
+ * @returns The loaded project definition
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const { project } = await loadSchema({
24
+ * schemaPath: 'src/tinybird/schema.ts',
25
+ * });
26
+ *
27
+ * console.log(project.datasources);
28
+ * console.log(project.pipes);
29
+ * ```
30
+ */
31
+ export async function loadSchema(options) {
32
+ const cwd = options.cwd ?? process.cwd();
33
+ const schemaPath = path.isAbsolute(options.schemaPath)
34
+ ? options.schemaPath
35
+ : path.resolve(cwd, options.schemaPath);
36
+ // Verify the file exists
37
+ if (!fs.existsSync(schemaPath)) {
38
+ throw new Error(`Schema file not found: ${schemaPath}`);
39
+ }
40
+ const schemaDir = path.dirname(schemaPath);
41
+ // Create a temporary output file for the bundle
42
+ const outfile = path.join(schemaDir, `.tinybird-schema-${Date.now()}.mjs`);
43
+ try {
44
+ // Bundle the schema with esbuild
45
+ await esbuild.build({
46
+ entryPoints: [schemaPath],
47
+ outfile,
48
+ bundle: true,
49
+ platform: "node",
50
+ format: "esm",
51
+ target: "node18",
52
+ // Mark @tinybirdco/sdk as external - it should already be installed
53
+ external: ["@tinybirdco/sdk"],
54
+ // Enable source maps for better error messages
55
+ sourcemap: "inline",
56
+ // Minify is off for debugging
57
+ minify: false,
58
+ });
59
+ // Import the bundled module
60
+ const moduleUrl = `file://${outfile}`;
61
+ const module = await import(moduleUrl);
62
+ // Look for the project definition
63
+ // It can be the default export or a named 'project' export
64
+ let project;
65
+ if (module.default && isProjectDefinition(module.default)) {
66
+ project = module.default;
67
+ }
68
+ else if (module.project && isProjectDefinition(module.project)) {
69
+ project = module.project;
70
+ }
71
+ else {
72
+ // Check all exports for a project definition
73
+ for (const key of Object.keys(module)) {
74
+ if (isProjectDefinition(module[key])) {
75
+ project = module[key];
76
+ break;
77
+ }
78
+ }
79
+ }
80
+ if (!project) {
81
+ throw new Error(`No ProjectDefinition found in ${schemaPath}. ` +
82
+ `Make sure to export a project created with defineProject().`);
83
+ }
84
+ return {
85
+ project,
86
+ schemaPath,
87
+ schemaDir,
88
+ };
89
+ }
90
+ finally {
91
+ // Clean up the temporary bundle file
92
+ try {
93
+ if (fs.existsSync(outfile)) {
94
+ fs.unlinkSync(outfile);
95
+ }
96
+ // Also clean up the source map if it was created separately
97
+ const sourcemapFile = outfile + ".map";
98
+ if (fs.existsSync(sourcemapFile)) {
99
+ fs.unlinkSync(sourcemapFile);
100
+ }
101
+ }
102
+ catch {
103
+ // Ignore cleanup errors
104
+ }
105
+ }
106
+ }
107
+ /**
108
+ * Load datasources and pipes from multiple TypeScript files
109
+ *
110
+ * Uses esbuild to bundle each file and scans exports for datasource
111
+ * and pipe definitions.
112
+ *
113
+ * @param options - Loader options
114
+ * @returns Discovered entities with metadata
115
+ *
116
+ * @example
117
+ * ```ts
118
+ * const entities = await loadEntities({
119
+ * includePaths: ['src/datasources.ts', 'src/pipes.ts'],
120
+ * });
121
+ *
122
+ * console.log(Object.keys(entities.datasources)); // ['pageViews', 'events']
123
+ * console.log(Object.keys(entities.pipes)); // ['topPages', 'topEvents']
124
+ * ```
125
+ */
126
+ export async function loadEntities(options) {
127
+ const cwd = options.cwd ?? process.cwd();
128
+ const result = {
129
+ datasources: {},
130
+ pipes: {},
131
+ sourceFiles: [],
132
+ };
133
+ for (const includePath of options.includePaths) {
134
+ const absolutePath = path.isAbsolute(includePath)
135
+ ? includePath
136
+ : path.resolve(cwd, includePath);
137
+ // Verify the file exists
138
+ if (!fs.existsSync(absolutePath)) {
139
+ throw new Error(`Include file not found: ${absolutePath}`);
140
+ }
141
+ result.sourceFiles.push(includePath);
142
+ const fileDir = path.dirname(absolutePath);
143
+ // Create a temporary output file for the bundle
144
+ const outfile = path.join(fileDir, `.tinybird-entities-${Date.now()}.mjs`);
145
+ try {
146
+ // Bundle the file with esbuild
147
+ await esbuild.build({
148
+ entryPoints: [absolutePath],
149
+ outfile,
150
+ bundle: true,
151
+ platform: "node",
152
+ format: "esm",
153
+ target: "node18",
154
+ // Mark @tinybirdco/sdk as external - it should already be installed
155
+ external: ["@tinybirdco/sdk"],
156
+ // Enable source maps for better error messages
157
+ sourcemap: "inline",
158
+ minify: false,
159
+ });
160
+ // Import the bundled module
161
+ const moduleUrl = `file://${outfile}`;
162
+ const module = await import(moduleUrl);
163
+ // Scan all exports for datasources and pipes
164
+ for (const [exportName, value] of Object.entries(module)) {
165
+ if (isDatasourceDefinition(value)) {
166
+ result.datasources[exportName] = {
167
+ definition: value,
168
+ info: {
169
+ exportName,
170
+ sourceFile: includePath,
171
+ },
172
+ };
173
+ }
174
+ else if (isPipeDefinition(value)) {
175
+ result.pipes[exportName] = {
176
+ definition: value,
177
+ info: {
178
+ exportName,
179
+ sourceFile: includePath,
180
+ },
181
+ };
182
+ }
183
+ }
184
+ }
185
+ finally {
186
+ // Clean up the temporary bundle file
187
+ try {
188
+ if (fs.existsSync(outfile)) {
189
+ fs.unlinkSync(outfile);
190
+ }
191
+ const sourcemapFile = outfile + ".map";
192
+ if (fs.existsSync(sourcemapFile)) {
193
+ fs.unlinkSync(sourcemapFile);
194
+ }
195
+ }
196
+ catch {
197
+ // Ignore cleanup errors
198
+ }
199
+ }
200
+ }
201
+ return result;
202
+ }
203
+ /**
204
+ * Convert loaded entities to a format compatible with generators
205
+ */
206
+ export function entitiesToProject(entities) {
207
+ const datasources = {};
208
+ const pipes = {};
209
+ for (const [name, { definition }] of Object.entries(entities.datasources)) {
210
+ datasources[name] = definition;
211
+ }
212
+ for (const [name, { definition }] of Object.entries(entities.pipes)) {
213
+ pipes[name] = definition;
214
+ }
215
+ return { datasources, pipes };
216
+ }
217
+ /**
218
+ * Watch a TypeScript schema file for changes
219
+ *
220
+ * Performs an initial load, then watches for file changes and reloads.
221
+ * Uses debouncing to coalesce rapid file system events.
222
+ *
223
+ * @param options - Watch options
224
+ * @returns A controller to stop watching
225
+ *
226
+ * @example
227
+ * ```ts
228
+ * const watcher = await watchSchema({
229
+ * schemaPath: 'src/tinybird/schema.ts',
230
+ * onChange: (schema) => {
231
+ * console.log('Schema updated:', schema.project);
232
+ * },
233
+ * onError: (err) => {
234
+ * console.error('Load error:', err.message);
235
+ * },
236
+ * });
237
+ *
238
+ * // Later, stop watching
239
+ * await watcher.close();
240
+ * ```
241
+ */
242
+ export async function watchSchema(options) {
243
+ const debounceMs = options.debounce ?? 100;
244
+ // Perform initial load
245
+ const initialSchema = await loadSchema(options);
246
+ const schemaPath = initialSchema.schemaPath;
247
+ const schemaDir = initialSchema.schemaDir;
248
+ // Set up debounced reload
249
+ let debounceTimer = null;
250
+ const reload = async () => {
251
+ try {
252
+ const result = await loadSchema(options);
253
+ await options.onChange(result);
254
+ }
255
+ catch (error) {
256
+ if (options.onError) {
257
+ options.onError(error);
258
+ }
259
+ }
260
+ };
261
+ const debouncedReload = () => {
262
+ if (debounceTimer) {
263
+ clearTimeout(debounceTimer);
264
+ }
265
+ debounceTimer = setTimeout(() => {
266
+ debounceTimer = null;
267
+ reload().catch((error) => {
268
+ if (options.onError) {
269
+ options.onError(error);
270
+ }
271
+ });
272
+ }, debounceMs);
273
+ };
274
+ // Watch the schema file and its directory for TypeScript files
275
+ const watcher = chokidarWatch([schemaPath, path.join(schemaDir, "**/*.ts")], {
276
+ ignoreInitial: true,
277
+ ignored: [
278
+ /node_modules/,
279
+ /\.tinybird-schema-.*\.mjs$/,
280
+ ],
281
+ });
282
+ watcher.on("change", debouncedReload);
283
+ watcher.on("add", debouncedReload);
284
+ watcher.on("unlink", debouncedReload);
285
+ return {
286
+ close: async () => {
287
+ if (debounceTimer) {
288
+ clearTimeout(debounceTimer);
289
+ }
290
+ await watcher.close();
291
+ },
292
+ initialSchema,
293
+ };
294
+ }
295
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/generator/loader.ts"],"names":[],"mappings":"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"}