@lobb-js/lobb-ext-reports 0.10.4 → 0.11.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.
- package/README.md +1 -0
- package/dist/index.js +5 -0
- package/dist/lib/components/pages/reports/components/chart.svelte +41 -15
- package/dist/lib/components/pages/reports/components/charts/table.svelte +0 -1
- package/dist/lib/components/pages/reports/components/report.svelte +107 -102
- package/dist/lib/components/pages/reports/index.svelte +3 -9
- package/dist/lib/components/pages/shared_report/index.svelte +109 -0
- package/dist/lib/components/pages/shared_report/index.svelte.d.ts +14 -0
- package/dist/lib/components/reportBody.svelte +114 -0
- package/dist/lib/components/reportBody.svelte.d.ts +14 -0
- package/extensions/reports/index.ts +2 -2
- package/extensions/reports/studio/index.ts +5 -0
- package/extensions/reports/studio/lib/components/pages/reports/components/chart.svelte +41 -15
- package/extensions/reports/studio/lib/components/pages/reports/components/charts/table.svelte +0 -1
- package/extensions/reports/studio/lib/components/pages/reports/components/report.svelte +107 -102
- package/extensions/reports/studio/lib/components/pages/reports/index.svelte +3 -9
- package/extensions/reports/studio/lib/components/pages/shared_report/index.svelte +109 -0
- package/extensions/reports/studio/lib/components/reportBody.svelte +114 -0
- package/extensions/reports/workflows.ts +73 -0
- package/package.json +4 -7
- package/dist/tests/analytics.spec.d.ts +0 -1
- package/dist/tests/analytics.spec.js +0 -17
- package/dist/tests/package.json +0 -1
- package/dist/tests/playwright.config.cjs +0 -27
- package/dist/tests/playwright.config.d.cts +0 -2
- package/extensions/reports/collectionRoutes.ts +0 -10
- package/extensions/reports/controllers/chartsController.ts +0 -78
- package/extensions/reports/studio/tests/analytics.spec.ts +0 -26
- package/extensions/reports/studio/tests/package.json +0 -1
- package/extensions/reports/studio/tests/playwright.config.cjs +0 -27
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Lobb, Workflow } from "@lobb-js/core";
|
|
2
|
+
import type { Context } from "hono";
|
|
3
|
+
|
|
4
|
+
export const workflows: Workflow[] = [
|
|
5
|
+
{
|
|
6
|
+
// Intercept GET /api/collections/reports_charts/:id when ?action=run_query
|
|
7
|
+
// is present — runs the chart's parsed function and short-circuits the
|
|
8
|
+
// default findOne behaviour by throwing a Response.
|
|
9
|
+
name: "reports_chartsRunQueryHandler",
|
|
10
|
+
eventName: "core.controllers.preFindOne",
|
|
11
|
+
handler: async (input, ctx) => {
|
|
12
|
+
if (input.collectionName !== "reports_charts") return input;
|
|
13
|
+
|
|
14
|
+
const c = input.context as Context;
|
|
15
|
+
const actionQuery = c.req.query("action");
|
|
16
|
+
if (!actionQuery) return input;
|
|
17
|
+
|
|
18
|
+
if (actionQuery !== "run_query") {
|
|
19
|
+
throw new ctx.LobbError({
|
|
20
|
+
code: "BAD_REQUEST",
|
|
21
|
+
message: `The passed (${actionQuery}) action query param is not supported`,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const lobb = c.get("lobb") as Lobb;
|
|
26
|
+
const reportRecordId = input.id;
|
|
27
|
+
const contextParam = c.req.query("context");
|
|
28
|
+
const context = JSON.parse(contextParam ?? "{}");
|
|
29
|
+
|
|
30
|
+
const driver = lobb.databaseService.getDriver();
|
|
31
|
+
const pool = driver.getConnection();
|
|
32
|
+
using client = await pool.connect();
|
|
33
|
+
|
|
34
|
+
const chartRecord = (await lobb.collectionService.findOne({
|
|
35
|
+
collectionName: "reports_charts",
|
|
36
|
+
client,
|
|
37
|
+
id: reportRecordId,
|
|
38
|
+
})).data;
|
|
39
|
+
|
|
40
|
+
if (!chartRecord) {
|
|
41
|
+
throw new ctx.LobbError({
|
|
42
|
+
code: "NOT_FOUND",
|
|
43
|
+
message: `The chart you are looking for does not exist.`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const pendingQueries: Promise<unknown>[] = [];
|
|
48
|
+
|
|
49
|
+
async function query(sql: string, args: Record<string, any>) {
|
|
50
|
+
const promise = client.query(sql, args).then((result) => result.rows);
|
|
51
|
+
pendingQueries.push(promise);
|
|
52
|
+
return await promise;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const chartReturnedValue = await lobb.utils.runParsedFunction(
|
|
57
|
+
chartRecord.chart,
|
|
58
|
+
query,
|
|
59
|
+
context,
|
|
60
|
+
);
|
|
61
|
+
await Promise.allSettled(pendingQueries);
|
|
62
|
+
throw new Response(JSON.stringify(chartReturnedValue), {
|
|
63
|
+
status: 200,
|
|
64
|
+
headers: { "Content-Type": "application/json" },
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (error instanceof Response) throw error;
|
|
68
|
+
await Promise.allSettled(pendingQueries);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobb-js/lobb-ext-reports",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -18,9 +18,8 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
|
-
"test": "bun
|
|
21
|
+
"test": "bun test extensions/reports/tests",
|
|
22
22
|
"test:lobb": "bun test extensions/reports/tests",
|
|
23
|
-
"test:studio": "bun --bun playwright test --config extensions/reports/studio/tests/playwright.config.cjs",
|
|
24
23
|
"dev": "bun run --watch lobb.ts",
|
|
25
24
|
"dev:studio": "vite dev",
|
|
26
25
|
"build": "vite build",
|
|
@@ -28,13 +27,12 @@
|
|
|
28
27
|
"prepare": "svelte-kit sync || echo ''",
|
|
29
28
|
"preview": "vite preview",
|
|
30
29
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
31
|
-
"postinstall": "bun --bun playwright install chromium",
|
|
32
30
|
"prepublishOnly": "lobb-ext-prepublish",
|
|
33
31
|
"postpublish": "lobb-ext-postpublish",
|
|
34
32
|
"package": "svelte-package --input extensions/reports/studio"
|
|
35
33
|
},
|
|
36
34
|
"dependencies": {
|
|
37
|
-
"@lobb-js/core": "^0.
|
|
35
|
+
"@lobb-js/core": "^0.32.1",
|
|
38
36
|
"chart.js": "^4.4.8",
|
|
39
37
|
"gridstack": "^12.6.0",
|
|
40
38
|
"hono": "^4.7.0",
|
|
@@ -45,8 +43,7 @@
|
|
|
45
43
|
},
|
|
46
44
|
"devDependencies": {
|
|
47
45
|
"@faker-js/faker": "^9.6.0",
|
|
48
|
-
"@
|
|
49
|
-
"@lobb-js/studio": "^0.28.5",
|
|
46
|
+
"@lobb-js/studio": "^0.29.1",
|
|
50
47
|
"@lucide/svelte": "^0.563.1",
|
|
51
48
|
"@sveltejs/adapter-node": "^5.5.4",
|
|
52
49
|
"@sveltejs/kit": "^2.60.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { test, expect } from "@playwright/test";
|
|
2
|
-
const ANALYTICS_URL = "/studio/extensions/reports/analytics";
|
|
3
|
-
test.describe("Analytics page", () => {
|
|
4
|
-
test.beforeEach(async ({ page }) => {
|
|
5
|
-
await page.goto(ANALYTICS_URL);
|
|
6
|
-
});
|
|
7
|
-
test("shows the analytics page", async ({ page }) => {
|
|
8
|
-
await expect(page).toHaveURL(new RegExp(ANALYTICS_URL));
|
|
9
|
-
});
|
|
10
|
-
test("shows empty state when no report is selected", async ({ page }) => {
|
|
11
|
-
await expect(page.getByText("No report selected")).toBeVisible();
|
|
12
|
-
await expect(page.getByText("Please select a report to view the details or create a new one")).toBeVisible();
|
|
13
|
-
});
|
|
14
|
-
test("shows create a report button in empty state", async ({ page }) => {
|
|
15
|
-
await expect(page.getByRole("button", { name: "Create a report" }).first()).toBeVisible();
|
|
16
|
-
});
|
|
17
|
-
});
|
package/dist/tests/package.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"type": "commonjs"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
const { defineConfig, devices } = require("@playwright/test");
|
|
2
|
-
|
|
3
|
-
module.exports = defineConfig({
|
|
4
|
-
testDir: __dirname,
|
|
5
|
-
testMatch: "**/*.spec.ts",
|
|
6
|
-
fullyParallel: true,
|
|
7
|
-
retries: 0,
|
|
8
|
-
expect: { timeout: 15000 },
|
|
9
|
-
use: {
|
|
10
|
-
baseURL: "http://localhost:3000",
|
|
11
|
-
trace: "on-first-retry",
|
|
12
|
-
headless: true,
|
|
13
|
-
},
|
|
14
|
-
projects: [
|
|
15
|
-
{
|
|
16
|
-
name: "chromium",
|
|
17
|
-
use: { ...devices["Desktop Chrome"] },
|
|
18
|
-
},
|
|
19
|
-
],
|
|
20
|
-
// Automatically start the dev server before running tests
|
|
21
|
-
webServer: {
|
|
22
|
-
command: "bun run dev",
|
|
23
|
-
url: "http://localhost:3000/studio",
|
|
24
|
-
reuseExistingServer: true,
|
|
25
|
-
cwd: "../../../../", // packages/reports-ext root
|
|
26
|
-
},
|
|
27
|
-
});
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import type { Context } from "hono";
|
|
2
|
-
import type { Lobb } from "@lobb-js/core";
|
|
3
|
-
import { LobbError } from "@lobb-js/core";
|
|
4
|
-
|
|
5
|
-
export class ChartsController {
|
|
6
|
-
public static async findOne(c: Context) {
|
|
7
|
-
const lobb = c.get("lobb") as Lobb;
|
|
8
|
-
const reportRecordId = c.req.param("id");
|
|
9
|
-
const actionQuery = c.req.query("action");
|
|
10
|
-
const context = c.req.query("context");
|
|
11
|
-
|
|
12
|
-
if (actionQuery) {
|
|
13
|
-
if (actionQuery === "run_query") {
|
|
14
|
-
return await handleRunQuery(
|
|
15
|
-
reportRecordId,
|
|
16
|
-
lobb,
|
|
17
|
-
c,
|
|
18
|
-
JSON.parse(context ?? "{}"),
|
|
19
|
-
);
|
|
20
|
-
} else {
|
|
21
|
-
throw new LobbError({
|
|
22
|
-
code: "BAD_REQUEST",
|
|
23
|
-
message:
|
|
24
|
-
`The passed (${actionQuery}) action query param is not supported`,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return await lobb.collectionControllers.findOne(
|
|
30
|
-
c,
|
|
31
|
-
) as Response;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function handleRunQuery(
|
|
36
|
-
reportRecordId: string,
|
|
37
|
-
lobb: Lobb,
|
|
38
|
-
c: Context,
|
|
39
|
-
context: Record<string, unknown>,
|
|
40
|
-
) {
|
|
41
|
-
const driver = lobb.databaseService.getDriver();
|
|
42
|
-
const pool = driver.getConnection();
|
|
43
|
-
using client = await pool.connect();
|
|
44
|
-
|
|
45
|
-
const chartRecord = (await lobb.collectionService.findOne({
|
|
46
|
-
collectionName: "reports_charts",
|
|
47
|
-
client,
|
|
48
|
-
id: reportRecordId,
|
|
49
|
-
})).data;
|
|
50
|
-
|
|
51
|
-
if (!chartRecord) {
|
|
52
|
-
throw new LobbError({
|
|
53
|
-
code: "NOT_FOUND",
|
|
54
|
-
message: `The chart you are looking for does not exist.`,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const pendingQueries: Promise<unknown>[] = [];
|
|
59
|
-
|
|
60
|
-
async function query(sql: string, args: Record<string, any>) {
|
|
61
|
-
const promise = client.query(sql, args).then((result) => result.rows);
|
|
62
|
-
pendingQueries.push(promise);
|
|
63
|
-
return await promise;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
const chartReturnedValue = await lobb.utils.runParsedFunction(
|
|
68
|
-
chartRecord.chart,
|
|
69
|
-
query,
|
|
70
|
-
context,
|
|
71
|
-
);
|
|
72
|
-
await Promise.allSettled(pendingQueries);
|
|
73
|
-
return c.json(chartReturnedValue, 200);
|
|
74
|
-
} catch (error) {
|
|
75
|
-
await Promise.allSettled(pendingQueries);
|
|
76
|
-
throw error;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { test, expect } from "@playwright/test";
|
|
2
|
-
|
|
3
|
-
const ANALYTICS_URL = "/studio/extensions/reports/analytics";
|
|
4
|
-
|
|
5
|
-
test.describe("Analytics page", () => {
|
|
6
|
-
test.beforeEach(async ({ page }) => {
|
|
7
|
-
await page.goto(ANALYTICS_URL);
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
test("shows the analytics page", async ({ page }) => {
|
|
11
|
-
await expect(page).toHaveURL(new RegExp(ANALYTICS_URL));
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
test("shows empty state when no report is selected", async ({ page }) => {
|
|
15
|
-
await expect(page.getByText("No report selected")).toBeVisible();
|
|
16
|
-
await expect(
|
|
17
|
-
page.getByText("Please select a report to view the details or create a new one")
|
|
18
|
-
).toBeVisible();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
test("shows create a report button in empty state", async ({ page }) => {
|
|
22
|
-
await expect(
|
|
23
|
-
page.getByRole("button", { name: "Create a report" }).first()
|
|
24
|
-
).toBeVisible();
|
|
25
|
-
});
|
|
26
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"type": "commonjs"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
const { defineConfig, devices } = require("@playwright/test");
|
|
2
|
-
|
|
3
|
-
module.exports = defineConfig({
|
|
4
|
-
testDir: __dirname,
|
|
5
|
-
testMatch: "**/*.spec.ts",
|
|
6
|
-
fullyParallel: true,
|
|
7
|
-
retries: 0,
|
|
8
|
-
expect: { timeout: 15000 },
|
|
9
|
-
use: {
|
|
10
|
-
baseURL: "http://localhost:3000",
|
|
11
|
-
trace: "on-first-retry",
|
|
12
|
-
headless: true,
|
|
13
|
-
},
|
|
14
|
-
projects: [
|
|
15
|
-
{
|
|
16
|
-
name: "chromium",
|
|
17
|
-
use: { ...devices["Desktop Chrome"] },
|
|
18
|
-
},
|
|
19
|
-
],
|
|
20
|
-
// Automatically start the dev server before running tests
|
|
21
|
-
webServer: {
|
|
22
|
-
command: "bun run dev",
|
|
23
|
-
url: "http://localhost:3000/studio",
|
|
24
|
-
reuseExistingServer: true,
|
|
25
|
-
cwd: "../../../../", // packages/reports-ext root
|
|
26
|
-
},
|
|
27
|
-
});
|