@malloy-publisher/server 0.0.118 → 0.0.120

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 (33) hide show
  1. package/dist/app/api-doc.yaml +324 -335
  2. package/dist/app/assets/HomePage-xhvGPTSO.js +1 -0
  3. package/dist/app/assets/MainPage-Bq95p8Cl.js +2 -0
  4. package/dist/app/assets/{ModelPage-CTrGQfsf.js → ModelPage-CbfBNWIi.js} +1 -1
  5. package/dist/app/assets/PackagePage-CGS612C4.js +1 -0
  6. package/dist/app/assets/ProjectPage-Dpn9pqSB.js +1 -0
  7. package/dist/app/assets/{RouteError-BgsaIu4c.js → RouteError-BLPhl1wC.js} +1 -1
  8. package/dist/app/assets/WorkbookPage-Dt93gSZ3.js +1 -0
  9. package/dist/app/assets/{index-bIu6ohLf.js → index-B8wuAjgG.js} +1 -1
  10. package/dist/app/assets/index-CVbROKL7.js +445 -0
  11. package/dist/app/assets/{index-BZ_1Ar9v.js → index-DxKW6bXB.js} +1 -1
  12. package/dist/app/assets/{index.umd-9JpsJxlU.js → index.umd-CVy5LWk2.js} +1 -1
  13. package/dist/app/index.html +1 -1
  14. package/dist/server.js +35396 -144724
  15. package/k6-tests/common.ts +12 -3
  16. package/package.json +4 -1
  17. package/src/controller/connection.controller.ts +82 -72
  18. package/src/controller/query.controller.ts +1 -1
  19. package/src/server.ts +6 -48
  20. package/src/service/connection.ts +384 -305
  21. package/src/service/db_utils.ts +407 -303
  22. package/src/service/package.spec.ts +8 -97
  23. package/src/service/package.ts +24 -46
  24. package/src/service/project.ts +8 -24
  25. package/src/service/project_store.ts +0 -1
  26. package/dist/app/assets/HomePage-ds2gUb3z.js +0 -1
  27. package/dist/app/assets/MainPage-arikDX4e.js +0 -1
  28. package/dist/app/assets/PackagePage-D8L11ZP_.js +0 -1
  29. package/dist/app/assets/ProjectPage-Dj8Z5I0J.js +0 -1
  30. package/dist/app/assets/WorkbookPage-McJT5YnW.js +0 -1
  31. package/dist/app/assets/index-CbVGARSr.js +0 -445
  32. package/src/controller/schedule.controller.ts +0 -21
  33. package/src/service/scheduler.ts +0 -190
@@ -1,21 +0,0 @@
1
- import { components } from "../api";
2
- import { ProjectStore } from "../service/project_store";
3
-
4
- type ApiSchedule = components["schemas"]["Schedule"];
5
-
6
- export class ScheduleController {
7
- private projectStore: ProjectStore;
8
-
9
- constructor(projectStore: ProjectStore) {
10
- this.projectStore = projectStore;
11
- }
12
-
13
- public async listSchedules(
14
- projectName: string,
15
- packageName: string,
16
- ): Promise<ApiSchedule[]> {
17
- const project = await this.projectStore?.getProject?.(projectName);
18
- const p = await project?.getPackage?.(packageName);
19
- return p?.listSchedules?.();
20
- }
21
- }
@@ -1,190 +0,0 @@
1
- import cron from "node-cron";
2
- import { components } from "../api";
3
- import { logger } from "../logger";
4
- import { Model } from "./model";
5
-
6
- // @ts-expect-error TODO: Fix missing Source type in API
7
- type ApiSource = components["schemas"]["Source"];
8
- type ApiView = components["schemas"]["View"];
9
- type ApiQuery = components["schemas"]["Query"];
10
- type ApiSchedule = components["schemas"]["Schedule"];
11
-
12
- const SCHEDULE_ANNOTATION = "# schedule";
13
-
14
- class Schedule {
15
- private model: Model;
16
- private source: ApiSource | undefined;
17
- private view: ApiView | undefined;
18
- private query: ApiQuery | undefined;
19
-
20
- private schedule: string;
21
- private action: string;
22
- private connection: string;
23
- private task: cron.ScheduledTask;
24
- private lastRunTime: number | undefined;
25
- private lastRunStatus: string;
26
-
27
- public constructor(
28
- model: Model,
29
- source: ApiSource | undefined,
30
- view: ApiView | undefined,
31
- query: ApiQuery | undefined,
32
- annotation: string,
33
- ) {
34
- this.model = model;
35
- this.source = source;
36
- this.view = view;
37
- this.query = query;
38
- const { origSchedule, cronSchedule, action, connection } =
39
- Schedule.parseAnnotation(annotation);
40
- this.schedule = origSchedule;
41
- this.action = action;
42
- this.connection = connection;
43
- this.lastRunTime = undefined;
44
- this.lastRunStatus = "unknown";
45
-
46
- this.task = cron.schedule(cronSchedule, () => {
47
- this.lastRunTime = Date.now();
48
- this.lastRunStatus = "ok";
49
- });
50
- }
51
-
52
- public stop() {
53
- this.task.stop();
54
- }
55
-
56
- public get(): ApiSchedule {
57
- const query = this.source
58
- ? `${this.source.name} > ${this.view?.name}`
59
- : this.query?.name;
60
- return {
61
- resource: `${this.model.getPath()} > ${query}`,
62
- schedule: this.schedule,
63
- action: this.action,
64
- connection: this.connection,
65
- lastRunTime: this.lastRunTime,
66
- lastRunStatus: this.lastRunStatus,
67
- };
68
- }
69
-
70
- private static parseAnnotation(annotation: string) {
71
- // Example schedule annotation
72
- // # schedule @hourly materialize duckdb
73
- // # schedule "0 * * * *" materialize duckdb
74
- // TODO: Don't split quoted strings. Use regex instead of split.
75
- const annotationSplit = annotation.split(/\s+/);
76
- if (annotationSplit.length != 6) {
77
- logger.info("Length: " + annotationSplit.length);
78
- throw new Error(
79
- "Invalid annotation string does not have enough parts: " +
80
- annotation,
81
- );
82
- }
83
-
84
- if (annotationSplit[0] != "#") {
85
- throw new Error(
86
- "Invalid annotation string does not have start with #: " +
87
- annotationSplit[0],
88
- );
89
- }
90
-
91
- if (annotationSplit[1] != "schedule") {
92
- throw new Error(
93
- "Invalid annotation string does not start with schedule command: " +
94
- annotationSplit[1],
95
- );
96
- }
97
-
98
- const standardCron = Schedule.translateNonStandardCron(
99
- annotationSplit[2],
100
- );
101
- if (!cron.validate(standardCron)) {
102
- throw new Error(
103
- "Invalid annotation string does not have valid cron schedule: " +
104
- standardCron,
105
- );
106
- }
107
-
108
- if (
109
- annotationSplit[3] != "materialize" &&
110
- annotationSplit[3] != "report"
111
- ) {
112
- throw new Error(
113
- "Invalid annotation string unrecognized command: " + annotation,
114
- );
115
- }
116
-
117
- // TODO: Validate connection exists.
118
-
119
- return {
120
- origSchedule: annotationSplit[2],
121
- cronSchedule: standardCron,
122
- action: annotationSplit[3],
123
- connection: annotationSplit[4],
124
- };
125
- }
126
-
127
- public static translateNonStandardCron(schedule: string): string {
128
- let standardCron = schedule;
129
- switch (schedule) {
130
- case "@yearly":
131
- case "@anually":
132
- standardCron = "0 0 1 1 *";
133
- break;
134
- case "@monthly":
135
- standardCron = "0 0 1 * *";
136
- break;
137
- case "@weekly":
138
- standardCron = "0 0 * * 0";
139
- break;
140
- case "@daily":
141
- case "@midnight":
142
- standardCron = "0 0 * * *";
143
- break;
144
- case "@hourly":
145
- standardCron = "0 * * * *";
146
- break;
147
- case "@minutely":
148
- standardCron = "* * * * *";
149
- }
150
- return standardCron;
151
- }
152
- }
153
-
154
- export class Scheduler {
155
- private schedules: Schedule[];
156
-
157
- private constructor(schedules: Schedule[]) {
158
- this.schedules = schedules;
159
- }
160
-
161
- public static create(models: Map<string, Model>): Scheduler {
162
- const schedules: Schedule[] = [];
163
-
164
- models.forEach((m) => {
165
- m.getSources()?.forEach((s) => {
166
- s.views?.forEach((v: ApiView) => {
167
- v.annotations?.forEach((a: string) => {
168
- if (a.startsWith(SCHEDULE_ANNOTATION)) {
169
- schedules.push(new Schedule(m, s, v, undefined, a));
170
- }
171
- });
172
- });
173
- });
174
-
175
- m.getQueries()?.forEach((q) => {
176
- q.annotations?.forEach((a) => {
177
- if (a.startsWith(SCHEDULE_ANNOTATION)) {
178
- schedules.push(new Schedule(m, undefined, undefined, q, a));
179
- }
180
- });
181
- });
182
- });
183
-
184
- return new Scheduler(schedules);
185
- }
186
-
187
- public list(): ApiSchedule[] {
188
- return this.schedules.map((s) => s.get());
189
- }
190
- }