trickle-backend 0.1.0

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 (65) hide show
  1. package/dist/db/connection.d.ts +3 -0
  2. package/dist/db/connection.js +16 -0
  3. package/dist/db/migrations.d.ts +2 -0
  4. package/dist/db/migrations.js +51 -0
  5. package/dist/db/queries.d.ts +70 -0
  6. package/dist/db/queries.js +186 -0
  7. package/dist/index.d.ts +1 -0
  8. package/dist/index.js +10 -0
  9. package/dist/routes/audit.d.ts +2 -0
  10. package/dist/routes/audit.js +251 -0
  11. package/dist/routes/codegen.d.ts +2 -0
  12. package/dist/routes/codegen.js +224 -0
  13. package/dist/routes/coverage.d.ts +2 -0
  14. package/dist/routes/coverage.js +98 -0
  15. package/dist/routes/dashboard.d.ts +2 -0
  16. package/dist/routes/dashboard.js +433 -0
  17. package/dist/routes/diff.d.ts +2 -0
  18. package/dist/routes/diff.js +181 -0
  19. package/dist/routes/errors.d.ts +2 -0
  20. package/dist/routes/errors.js +86 -0
  21. package/dist/routes/functions.d.ts +2 -0
  22. package/dist/routes/functions.js +69 -0
  23. package/dist/routes/ingest.d.ts +2 -0
  24. package/dist/routes/ingest.js +111 -0
  25. package/dist/routes/mock.d.ts +2 -0
  26. package/dist/routes/mock.js +57 -0
  27. package/dist/routes/search.d.ts +2 -0
  28. package/dist/routes/search.js +136 -0
  29. package/dist/routes/tail.d.ts +2 -0
  30. package/dist/routes/tail.js +11 -0
  31. package/dist/routes/types.d.ts +2 -0
  32. package/dist/routes/types.js +97 -0
  33. package/dist/server.d.ts +2 -0
  34. package/dist/server.js +40 -0
  35. package/dist/services/sse-broker.d.ts +10 -0
  36. package/dist/services/sse-broker.js +39 -0
  37. package/dist/services/type-differ.d.ts +2 -0
  38. package/dist/services/type-differ.js +126 -0
  39. package/dist/services/type-generator.d.ts +319 -0
  40. package/dist/services/type-generator.js +3207 -0
  41. package/dist/types.d.ts +56 -0
  42. package/dist/types.js +2 -0
  43. package/package.json +22 -0
  44. package/src/db/connection.ts +16 -0
  45. package/src/db/migrations.ts +50 -0
  46. package/src/db/queries.ts +260 -0
  47. package/src/index.ts +11 -0
  48. package/src/routes/audit.ts +283 -0
  49. package/src/routes/codegen.ts +237 -0
  50. package/src/routes/coverage.ts +120 -0
  51. package/src/routes/dashboard.ts +435 -0
  52. package/src/routes/diff.ts +215 -0
  53. package/src/routes/errors.ts +91 -0
  54. package/src/routes/functions.ts +75 -0
  55. package/src/routes/ingest.ts +139 -0
  56. package/src/routes/mock.ts +66 -0
  57. package/src/routes/search.ts +169 -0
  58. package/src/routes/tail.ts +12 -0
  59. package/src/routes/types.ts +106 -0
  60. package/src/server.ts +40 -0
  61. package/src/services/sse-broker.ts +51 -0
  62. package/src/services/type-differ.ts +141 -0
  63. package/src/services/type-generator.ts +3853 -0
  64. package/src/types.ts +37 -0
  65. package/tsconfig.json +8 -0
@@ -0,0 +1,51 @@
1
+ import { EventEmitter } from "events";
2
+ import { Response } from "express";
3
+
4
+ interface SseClient {
5
+ res: Response;
6
+ filter?: string;
7
+ }
8
+
9
+ class SseBroker extends EventEmitter {
10
+ private clients: SseClient[] = [];
11
+
12
+ addClient(res: Response, filter?: string): void {
13
+ res.writeHead(200, {
14
+ "Content-Type": "text/event-stream",
15
+ "Cache-Control": "no-cache",
16
+ Connection: "keep-alive",
17
+ "X-Accel-Buffering": "no",
18
+ });
19
+ res.write(":\n\n"); // initial comment to establish connection
20
+
21
+ const client: SseClient = { res, filter };
22
+ this.clients.push(client);
23
+
24
+ res.on("close", () => {
25
+ this.removeClient(res);
26
+ });
27
+ }
28
+
29
+ removeClient(res: Response): void {
30
+ this.clients = this.clients.filter((c) => c.res !== res);
31
+ }
32
+
33
+ broadcast(event: string, data: unknown): void {
34
+ const payload = JSON.stringify(data);
35
+ const functionName =
36
+ typeof data === "object" && data !== null && "functionName" in data
37
+ ? (data as { functionName: string }).functionName
38
+ : undefined;
39
+
40
+ for (const client of this.clients) {
41
+ if (client.filter && functionName) {
42
+ if (!functionName.includes(client.filter)) {
43
+ continue;
44
+ }
45
+ }
46
+ client.res.write(`event: ${event}\ndata: ${payload}\n\n`);
47
+ }
48
+ }
49
+ }
50
+
51
+ export const sseBroker = new SseBroker();
@@ -0,0 +1,141 @@
1
+ import { TypeNode, TypeDiff } from "../types";
2
+
3
+ export function diffTypes(from: TypeNode, to: TypeNode, basePath: string = ""): TypeDiff[] {
4
+ const diffs: TypeDiff[] = [];
5
+
6
+ if (from.kind !== to.kind) {
7
+ diffs.push({ kind: "changed", path: basePath || "(root)", from, to });
8
+ return diffs;
9
+ }
10
+
11
+ switch (from.kind) {
12
+ case "primitive": {
13
+ const toNode = to as Extract<TypeNode, { kind: "primitive" }>;
14
+ if (from.name !== toNode.name) {
15
+ diffs.push({ kind: "changed", path: basePath || "(root)", from, to });
16
+ }
17
+ break;
18
+ }
19
+
20
+ case "object": {
21
+ const toNode = to as Extract<TypeNode, { kind: "object" }>;
22
+ const fromKeys = new Set(Object.keys(from.properties));
23
+ const toKeys = new Set(Object.keys(toNode.properties));
24
+
25
+ for (const key of fromKeys) {
26
+ const childPath = basePath ? `${basePath}.${key}` : key;
27
+ if (!toKeys.has(key)) {
28
+ diffs.push({ kind: "removed", path: childPath, type: from.properties[key] });
29
+ } else {
30
+ diffs.push(...diffTypes(from.properties[key], toNode.properties[key], childPath));
31
+ }
32
+ }
33
+
34
+ for (const key of toKeys) {
35
+ if (!fromKeys.has(key)) {
36
+ const childPath = basePath ? `${basePath}.${key}` : key;
37
+ diffs.push({ kind: "added", path: childPath, type: toNode.properties[key] });
38
+ }
39
+ }
40
+ break;
41
+ }
42
+
43
+ case "array": {
44
+ const toNode = to as Extract<TypeNode, { kind: "array" }>;
45
+ diffs.push(...diffTypes(from.element, toNode.element, `${basePath || "(root)"}[]`));
46
+ break;
47
+ }
48
+
49
+ case "union": {
50
+ const toNode = to as Extract<TypeNode, { kind: "union" }>;
51
+ const fromSerialized = from.members.map((m) => JSON.stringify(m));
52
+ const toSerialized = toNode.members.map((m) => JSON.stringify(m));
53
+ const fromSet = new Set(fromSerialized);
54
+ const toSet = new Set(toSerialized);
55
+
56
+ for (let i = 0; i < fromSerialized.length; i++) {
57
+ if (!toSet.has(fromSerialized[i])) {
58
+ diffs.push({
59
+ kind: "removed",
60
+ path: `${basePath || "(root)"}|[${i}]`,
61
+ type: from.members[i],
62
+ });
63
+ }
64
+ }
65
+ for (let i = 0; i < toSerialized.length; i++) {
66
+ if (!fromSet.has(toSerialized[i])) {
67
+ diffs.push({
68
+ kind: "added",
69
+ path: `${basePath || "(root)"}|[${i}]`,
70
+ type: toNode.members[i],
71
+ });
72
+ }
73
+ }
74
+ break;
75
+ }
76
+
77
+ case "function": {
78
+ const toNode = to as Extract<TypeNode, { kind: "function" }>;
79
+ const maxParams = Math.max(from.params.length, toNode.params.length);
80
+ for (let i = 0; i < maxParams; i++) {
81
+ const paramPath = `${basePath || "(root)"}.params[${i}]`;
82
+ if (i >= from.params.length) {
83
+ diffs.push({ kind: "added", path: paramPath, type: toNode.params[i] });
84
+ } else if (i >= toNode.params.length) {
85
+ diffs.push({ kind: "removed", path: paramPath, type: from.params[i] });
86
+ } else {
87
+ diffs.push(...diffTypes(from.params[i], toNode.params[i], paramPath));
88
+ }
89
+ }
90
+ diffs.push(
91
+ ...diffTypes(from.returnType, toNode.returnType, `${basePath || "(root)"}.return`)
92
+ );
93
+ break;
94
+ }
95
+
96
+ case "promise": {
97
+ const toNode = to as Extract<TypeNode, { kind: "promise" }>;
98
+ diffs.push(
99
+ ...diffTypes(from.resolved, toNode.resolved, `${basePath || "(root)"}<resolved>`)
100
+ );
101
+ break;
102
+ }
103
+
104
+ case "map": {
105
+ const toNode = to as Extract<TypeNode, { kind: "map" }>;
106
+ diffs.push(...diffTypes(from.key, toNode.key, `${basePath || "(root)"}<key>`));
107
+ diffs.push(...diffTypes(from.value, toNode.value, `${basePath || "(root)"}<value>`));
108
+ break;
109
+ }
110
+
111
+ case "set": {
112
+ const toNode = to as Extract<TypeNode, { kind: "set" }>;
113
+ diffs.push(
114
+ ...diffTypes(from.element, toNode.element, `${basePath || "(root)"}<element>`)
115
+ );
116
+ break;
117
+ }
118
+
119
+ case "tuple": {
120
+ const toNode = to as Extract<TypeNode, { kind: "tuple" }>;
121
+ const maxLen = Math.max(from.elements.length, toNode.elements.length);
122
+ for (let i = 0; i < maxLen; i++) {
123
+ const elPath = `${basePath || "(root)"}[${i}]`;
124
+ if (i >= from.elements.length) {
125
+ diffs.push({ kind: "added", path: elPath, type: toNode.elements[i] });
126
+ } else if (i >= toNode.elements.length) {
127
+ diffs.push({ kind: "removed", path: elPath, type: from.elements[i] });
128
+ } else {
129
+ diffs.push(...diffTypes(from.elements[i], toNode.elements[i], elPath));
130
+ }
131
+ }
132
+ break;
133
+ }
134
+
135
+ case "unknown":
136
+ // Both unknown — no diff
137
+ break;
138
+ }
139
+
140
+ return diffs;
141
+ }