@graphenedata/cli 0.0.15 → 0.0.16

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 (117) hide show
  1. package/README.md +138 -0
  2. package/dist/cli/bigQuery-I3F46SC6.js +75 -0
  3. package/dist/cli/bigQuery-I3F46SC6.js.map +7 -0
  4. package/dist/cli/chunk-OVWODUTJ.js +12849 -0
  5. package/dist/cli/chunk-OVWODUTJ.js.map +7 -0
  6. package/dist/cli/chunk-QAXEOZ43.js +53 -0
  7. package/dist/cli/chunk-QAXEOZ43.js.map +7 -0
  8. package/dist/cli/cli.js +234 -11197
  9. package/dist/cli/clickhouse-ZN5AN2UL.js +64 -0
  10. package/dist/cli/clickhouse-ZN5AN2UL.js.map +7 -0
  11. package/dist/cli/duckdb-IYBIO5KJ.js +87 -0
  12. package/dist/cli/duckdb-IYBIO5KJ.js.map +7 -0
  13. package/dist/cli/serve2-TNN5EROW.js +447 -0
  14. package/dist/cli/serve2-TNN5EROW.js.map +7 -0
  15. package/dist/cli/snowflake-MOQB5GA4.js +128 -0
  16. package/dist/cli/snowflake-MOQB5GA4.js.map +7 -0
  17. package/dist/index.d.ts +63 -0
  18. package/dist/lang/index.d.ts +63 -0
  19. package/dist/skills/graphene/SKILL.md +150 -96
  20. package/dist/skills/graphene/references/big-value.md +6 -41
  21. package/dist/skills/graphene/references/date-range.md +64 -0
  22. package/dist/skills/graphene/references/dropdown.md +3 -4
  23. package/dist/skills/graphene/references/echarts.md +162 -0
  24. package/dist/skills/graphene/references/gsql.md +55 -25
  25. package/dist/skills/graphene/references/model-gsql.md +72 -0
  26. package/dist/skills/graphene/references/table.md +13 -14
  27. package/dist/skills/graphene/references/text-input.md +2 -1
  28. package/dist/ui/app.css +239 -340
  29. package/dist/ui/component-utilities/dataShaping.ts +484 -0
  30. package/dist/ui/component-utilities/dataSummary.ts +57 -0
  31. package/dist/ui/component-utilities/enrich.ts +763 -0
  32. package/dist/ui/component-utilities/format.ts +177 -0
  33. package/dist/ui/component-utilities/inputUtils.ts +44 -8
  34. package/dist/ui/component-utilities/theme.ts +200 -0
  35. package/dist/ui/component-utilities/themeStores.ts +21 -8
  36. package/dist/ui/component-utilities/types.ts +70 -0
  37. package/dist/ui/components/AreaChart.svelte +57 -105
  38. package/dist/ui/components/BarChart.svelte +71 -129
  39. package/dist/ui/components/BigValue.svelte +24 -40
  40. package/dist/ui/components/Column.svelte +10 -18
  41. package/dist/ui/components/DateRange.svelte +54 -21
  42. package/dist/ui/components/Dropdown.svelte +47 -26
  43. package/dist/ui/components/DropdownOption.svelte +1 -2
  44. package/dist/ui/components/ECharts.svelte +181 -67
  45. package/dist/ui/components/InlineDelta.svelte +50 -31
  46. package/dist/ui/components/LineChart.svelte +54 -125
  47. package/dist/ui/components/PieChart.svelte +27 -37
  48. package/dist/ui/components/QueryLoad.svelte +77 -45
  49. package/dist/ui/components/Row.svelte +2 -1
  50. package/dist/ui/components/ScatterPlot.svelte +52 -0
  51. package/dist/ui/components/Skeleton.svelte +32 -0
  52. package/dist/ui/components/Table.svelte +3 -2
  53. package/dist/ui/components/TableGroupRow.svelte +28 -36
  54. package/dist/ui/components/TableHarness.svelte +32 -0
  55. package/dist/ui/components/TableHeader.svelte +34 -59
  56. package/dist/ui/components/TableRow.svelte +14 -38
  57. package/dist/ui/components/TableSubtotalRow.svelte +18 -21
  58. package/dist/ui/components/TableTotalRow.svelte +27 -37
  59. package/dist/ui/components/TextInput.svelte +13 -12
  60. package/dist/ui/components/Value.svelte +25 -0
  61. package/dist/ui/components/_Table.svelte +72 -70
  62. package/dist/ui/internal/ChartGallery.svelte +527 -0
  63. package/dist/ui/internal/ErrorDisplay.svelte +22 -97
  64. package/dist/ui/internal/LocalApp.svelte +80 -17
  65. package/dist/ui/internal/PageNavGroup.svelte +269 -0
  66. package/dist/ui/internal/Sidebar.svelte +178 -0
  67. package/dist/ui/internal/SidebarToggle.svelte +47 -0
  68. package/dist/ui/internal/StyleGallery.svelte +244 -0
  69. package/dist/ui/internal/clientCache.ts +2 -2
  70. package/dist/ui/internal/pageInputs.svelte.js +292 -0
  71. package/dist/ui/internal/queryEngine.ts +102 -117
  72. package/dist/ui/internal/runSocket.ts +32 -12
  73. package/dist/ui/internal/sidebar.svelte.js +18 -0
  74. package/dist/ui/internal/telemetry.ts +51 -16
  75. package/dist/ui/internal/types.d.ts +7 -0
  76. package/dist/ui/web.js +28 -11
  77. package/package.json +36 -38
  78. package/dist/skills/graphene/references/area-chart.md +0 -95
  79. package/dist/skills/graphene/references/bar-chart.md +0 -112
  80. package/dist/skills/graphene/references/line-chart.md +0 -108
  81. package/dist/skills/graphene/references/pie-chart.md +0 -29
  82. package/dist/skills/graphene/references/value-formats.md +0 -104
  83. package/dist/ui/component-utilities/autoFormatting.js +0 -280
  84. package/dist/ui/component-utilities/builtInFormats.js +0 -481
  85. package/dist/ui/component-utilities/chartContext.js +0 -12
  86. package/dist/ui/component-utilities/chartWindowDebug.js +0 -21
  87. package/dist/ui/component-utilities/checkInputs.js +0 -84
  88. package/dist/ui/component-utilities/convert.js +0 -15
  89. package/dist/ui/component-utilities/dateParsing.js +0 -56
  90. package/dist/ui/component-utilities/dropdownContext.ts +0 -1
  91. package/dist/ui/component-utilities/echarts.js +0 -252
  92. package/dist/ui/component-utilities/echartsThemes.js +0 -443
  93. package/dist/ui/component-utilities/formatTitle.js +0 -24
  94. package/dist/ui/component-utilities/formatting.js +0 -241
  95. package/dist/ui/component-utilities/getColumnExtents.js +0 -79
  96. package/dist/ui/component-utilities/getColumnSummary.js +0 -62
  97. package/dist/ui/component-utilities/getCompletedData.js +0 -122
  98. package/dist/ui/component-utilities/getDistinctCount.js +0 -7
  99. package/dist/ui/component-utilities/getDistinctValues.js +0 -15
  100. package/dist/ui/component-utilities/getSeriesConfig.js +0 -231
  101. package/dist/ui/component-utilities/getSortedData.js +0 -9
  102. package/dist/ui/component-utilities/getStackPercentages.js +0 -45
  103. package/dist/ui/component-utilities/getStackedData.js +0 -19
  104. package/dist/ui/component-utilities/getYAxisIndex.js +0 -15
  105. package/dist/ui/component-utilities/globalContexts.js +0 -1
  106. package/dist/ui/component-utilities/helpers/getCompletedData.helpers.js +0 -119
  107. package/dist/ui/component-utilities/replaceNulls.js +0 -16
  108. package/dist/ui/component-utilities/tableUtils.ts +0 -107
  109. package/dist/ui/component-utilities/tidyWithTypes.js +0 -9
  110. package/dist/ui/components/Area.svelte +0 -214
  111. package/dist/ui/components/Bar.svelte +0 -347
  112. package/dist/ui/components/Chart.svelte +0 -995
  113. package/dist/ui/components/Line.svelte +0 -227
  114. package/dist/ui/internal/NavSidebar.svelte +0 -396
  115. package/dist/ui/internal/theme.ts +0 -60
  116. package/dist/ui/public/inter-latin-ext.woff2 +0 -0
  117. package/dist/ui/public/inter-latin.woff2 +0 -0
@@ -0,0 +1,64 @@
1
+ // connections/clickhouse.ts
2
+ import { createClient } from "@clickhouse/client";
3
+ var ClickHouseConnection = class {
4
+ client;
5
+ defaultDatabase;
6
+ constructor(options) {
7
+ this.defaultDatabase = options.database || "default";
8
+ this.client = createClient({
9
+ url: options.url,
10
+ username: options.username,
11
+ password: options.password,
12
+ database: this.defaultDatabase,
13
+ application: "Graphene"
14
+ });
15
+ }
16
+ async runQuery(sql, _params) {
17
+ let result = await this.client.query({ query: sql, format: "JSONEachRow" });
18
+ let rows = await result.json();
19
+ return { rows, totalRows: rows.length };
20
+ }
21
+ async listDatasets() {
22
+ let res = await this.runQuery(`
23
+ select name
24
+ from system.databases
25
+ where lower(name) not in ('system', 'information_schema')
26
+ order by name
27
+ `);
28
+ return res.rows.map((row) => String(row["name"]).toLowerCase());
29
+ }
30
+ async listTables(database = this.defaultDatabase) {
31
+ let sql = `
32
+ select database, name
33
+ from system.tables
34
+ where lower(database) = lower('${escapeClickHouseString(database)}')
35
+ order by name
36
+ `.trim();
37
+ let res = await this.runQuery(sql);
38
+ return res.rows.map((row) => `${String(row["database"]).toLowerCase()}.${String(row["name"]).toLowerCase()}`);
39
+ }
40
+ async describeTable(target) {
41
+ let parts = target.split(".").filter(Boolean);
42
+ let table = parts.pop() || "";
43
+ let database = parts.join(".") || this.defaultDatabase;
44
+ let sql = `
45
+ select name, type, position
46
+ from system.columns
47
+ where lower(database) = lower('${escapeClickHouseString(database)}')
48
+ and lower(table) = lower('${escapeClickHouseString(table)}')
49
+ order by position
50
+ `.trim();
51
+ let res = await this.runQuery(sql);
52
+ return res.rows.map((row) => ({ name: String(row["name"]).toLowerCase(), dataType: String(row["type"]) }));
53
+ }
54
+ async close() {
55
+ await this.client.close();
56
+ }
57
+ };
58
+ function escapeClickHouseString(value) {
59
+ return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
60
+ }
61
+ export {
62
+ ClickHouseConnection
63
+ };
64
+ //# sourceMappingURL=clickhouse-ZN5AN2UL.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../connections/clickhouse.ts"],
4
+ "sourcesContent": ["import {createClient, type ClickHouseClient} from '@clickhouse/client'\n\nimport {type QueryConnection, type QueryResult, type QueryParams, type SchemaColumn} from './types.ts'\n\nexport interface ClickHouseOptions {\n url: string\n username: string\n password: string\n database?: string\n}\n\nexport class ClickHouseConnection implements QueryConnection {\n private client: ClickHouseClient\n private defaultDatabase: string\n\n constructor(options: ClickHouseOptions) {\n this.defaultDatabase = options.database || 'default'\n this.client = createClient({\n url: options.url,\n username: options.username,\n password: options.password,\n database: this.defaultDatabase,\n application: 'Graphene',\n })\n }\n\n async runQuery(sql: string, _params?: QueryParams): Promise<QueryResult> {\n let result = await this.client.query({query: sql, format: 'JSONEachRow'})\n let rows = (await result.json()) as Array<Record<string, unknown>>\n return {rows, totalRows: rows.length}\n }\n\n async listDatasets(): Promise<string[]> {\n let res = await this.runQuery(`\n select name\n from system.databases\n where lower(name) not in ('system', 'information_schema')\n order by name\n `)\n return res.rows.map(row => String(row['name']).toLowerCase())\n }\n\n async listTables(database = this.defaultDatabase): Promise<string[]> {\n let sql = `\n select database, name\n from system.tables\n where lower(database) = lower('${escapeClickHouseString(database)}')\n order by name\n `.trim()\n let res = await this.runQuery(sql)\n return res.rows.map(row => `${String(row['database']).toLowerCase()}.${String(row['name']).toLowerCase()}`)\n }\n\n async describeTable(target: string): Promise<SchemaColumn[]> {\n let parts = target.split('.').filter(Boolean)\n let table = parts.pop() || ''\n let database = parts.join('.') || this.defaultDatabase\n let sql = `\n select name, type, position\n from system.columns\n where lower(database) = lower('${escapeClickHouseString(database)}')\n and lower(table) = lower('${escapeClickHouseString(table)}')\n order by position\n `.trim()\n let res = await this.runQuery(sql)\n return res.rows.map(row => ({name: String(row['name']).toLowerCase(), dataType: String(row['type'])}))\n }\n\n async close(): Promise<void> {\n await this.client.close()\n }\n}\n\nfunction escapeClickHouseString(value: string) {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")\n}\n"],
5
+ "mappings": ";AAAA,SAAQ,oBAA0C;AAW3C,IAAM,uBAAN,MAAsD;AAAA,EACnD;AAAA,EACA;AAAA,EAER,YAAY,SAA4B;AACtC,SAAK,kBAAkB,QAAQ,YAAY;AAC3C,SAAK,SAAS,aAAa;AAAA,MACzB,KAAK,QAAQ;AAAA,MACb,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,MAClB,UAAU,KAAK;AAAA,MACf,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,SAAS,KAAa,SAA6C;AACvE,QAAI,SAAS,MAAM,KAAK,OAAO,MAAM,EAAC,OAAO,KAAK,QAAQ,cAAa,CAAC;AACxE,QAAI,OAAQ,MAAM,OAAO,KAAK;AAC9B,WAAO,EAAC,MAAM,WAAW,KAAK,OAAM;AAAA,EACtC;AAAA,EAEA,MAAM,eAAkC;AACtC,QAAI,MAAM,MAAM,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,KAK7B;AACD,WAAO,IAAI,KAAK,IAAI,SAAO,OAAO,IAAI,MAAM,CAAC,EAAE,YAAY,CAAC;AAAA,EAC9D;AAAA,EAEA,MAAM,WAAW,WAAW,KAAK,iBAAoC;AACnE,QAAI,MAAM;AAAA;AAAA;AAAA,uCAGyB,uBAAuB,QAAQ,CAAC;AAAA;AAAA,MAEjE,KAAK;AACP,QAAI,MAAM,MAAM,KAAK,SAAS,GAAG;AACjC,WAAO,IAAI,KAAK,IAAI,SAAO,GAAG,OAAO,IAAI,UAAU,CAAC,EAAE,YAAY,CAAC,IAAI,OAAO,IAAI,MAAM,CAAC,EAAE,YAAY,CAAC,EAAE;AAAA,EAC5G;AAAA,EAEA,MAAM,cAAc,QAAyC;AAC3D,QAAI,QAAQ,OAAO,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5C,QAAI,QAAQ,MAAM,IAAI,KAAK;AAC3B,QAAI,WAAW,MAAM,KAAK,GAAG,KAAK,KAAK;AACvC,QAAI,MAAM;AAAA;AAAA;AAAA,uCAGyB,uBAAuB,QAAQ,CAAC;AAAA,oCACnC,uBAAuB,KAAK,CAAC;AAAA;AAAA,MAE3D,KAAK;AACP,QAAI,MAAM,MAAM,KAAK,SAAS,GAAG;AACjC,WAAO,IAAI,KAAK,IAAI,UAAQ,EAAC,MAAM,OAAO,IAAI,MAAM,CAAC,EAAE,YAAY,GAAG,UAAU,OAAO,IAAI,MAAM,CAAC,EAAC,EAAE;AAAA,EACvG;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,OAAO,MAAM;AAAA,EAC1B;AACF;AAEA,SAAS,uBAAuB,OAAe;AAC7C,SAAO,MAAM,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK;AACzD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,87 @@
1
+ import {
2
+ config
3
+ } from "./chunk-QAXEOZ43.js";
4
+
5
+ // connections/duckdb.ts
6
+ import { DuckDBTimestampValue, DuckDBInstance, DuckDBDateValue, DuckDBDecimalValue } from "@duckdb/node-api";
7
+ import { promises as fs } from "fs";
8
+ import path from "path";
9
+ var DuckDBConnection = class {
10
+ options;
11
+ ready;
12
+ connection = null;
13
+ constructor(options) {
14
+ this.options = options || {};
15
+ this.ready = this.initialize();
16
+ }
17
+ async initialize() {
18
+ let dbPath = this.options.path || config.duckdb?.path;
19
+ if (!dbPath) {
20
+ let files = await fs.readdir(config.root);
21
+ dbPath = files.find((f) => f.endsWith(".duckdb"));
22
+ if (!dbPath) throw new Error("No .duckdb file found in current directory");
23
+ }
24
+ if (!path.isAbsolute(dbPath)) dbPath = path.resolve(config.root, dbPath);
25
+ let db = await DuckDBInstance.create(":memory:");
26
+ this.connection = await db.connect();
27
+ let escapedPath = dbPath.replace(/'/g, "''");
28
+ await this.connection.run(`attach '${escapedPath}' as graphene_cli (READ_ONLY);`);
29
+ await this.connection.run("use graphene_cli;");
30
+ }
31
+ async runQuery(sql, params) {
32
+ await this.ready;
33
+ let reader = params ? await this.connection.runAndReadAll(sql, params) : await this.connection.runAndReadAll(sql);
34
+ let rows = reader.getRowObjects().map((record) => {
35
+ let out = {};
36
+ for (let [k, v] of Object.entries(record)) {
37
+ if (typeof v === "bigint") out[k] = Number(v);
38
+ else if (v === null) out[k] = null;
39
+ else if (v instanceof DuckDBTimestampValue) out[k] = new Date(Number(v.micros / 1000n)).toUTCString();
40
+ else if (v instanceof DuckDBDateValue) out[k] = v.toString();
41
+ else if (v instanceof DuckDBDecimalValue) out[k] = v.toDouble();
42
+ else if (typeof v === "object") throw new Error(`Unsupported datatype ${v.constructor?.name}`);
43
+ else out[k] = v;
44
+ }
45
+ return out;
46
+ });
47
+ return { rows };
48
+ }
49
+ async listDatasets() {
50
+ return await Promise.resolve([]);
51
+ }
52
+ async listTables() {
53
+ let sql = `
54
+ select table_schema as table_schema, table_name as table_name
55
+ from information_schema.tables
56
+ where table_type in ('BASE TABLE', 'VIEW') and table_schema not in ('information_schema', 'pg_catalog')
57
+ order by table_schema, table_name
58
+ `.trim();
59
+ let res = await this.runQuery(sql);
60
+ return res.rows.map((row) => String(row["table_name"]).toLowerCase());
61
+ }
62
+ async describeTable(target) {
63
+ let parts = target.split(".");
64
+ let table = parts.pop() || "";
65
+ let schema = parts[0];
66
+ let schemaFilter = schema ? "lower(table_schema) = lower($2)" : "table_schema not in ('information_schema', 'pg_catalog')";
67
+ let sql = `
68
+ select column_name as column_name, data_type as data_type, ordinal_position as ordinal_position
69
+ from information_schema.columns
70
+ where lower(table_name) = lower($1) and ${schemaFilter}
71
+ order by ordinal_position
72
+ `.trim();
73
+ let params = schema ? [table, schema] : [table];
74
+ let res = await this.runQuery(sql, params);
75
+ return res.rows.map((row) => {
76
+ return { name: String(row["column_name"]).toLowerCase(), dataType: String(row["data_type"]) };
77
+ });
78
+ }
79
+ async close() {
80
+ await this.ready;
81
+ this.connection?.closeSync();
82
+ }
83
+ };
84
+ export {
85
+ DuckDBConnection
86
+ };
87
+ //# sourceMappingURL=duckdb-IYBIO5KJ.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../connections/duckdb.ts"],
4
+ "sourcesContent": ["import {DuckDBTimestampValue, DuckDBInstance, DuckDBDateValue, DuckDBDecimalValue, type DuckDBConnection as InnerConnection} from '@duckdb/node-api'\nimport {promises as fs} from 'fs'\nimport path from 'path'\n\nimport {config} from '../../lang/config.ts'\nimport {type QueryResult, type QueryConnection, type SchemaColumn, type QueryParams} from './types.ts'\n\ninterface DuckDbOptions {\n path?: string\n}\n\nexport class DuckDBConnection implements QueryConnection {\n options: DuckDbOptions\n ready: Promise<void>\n connection: InnerConnection | null = null\n\n constructor(options?: DuckDbOptions) {\n this.options = options || {}\n this.ready = this.initialize()\n }\n\n private async initialize() {\n let dbPath = this.options.path || config.duckdb?.path\n if (!dbPath) {\n let files = await fs.readdir(config.root)\n dbPath = files.find(f => f.endsWith('.duckdb'))\n if (!dbPath) throw new Error('No .duckdb file found in current directory')\n }\n if (!path.isAbsolute(dbPath)) dbPath = path.resolve(config.root, dbPath)\n\n let db = await DuckDBInstance.create(':memory:')\n this.connection = await db.connect()\n let escapedPath = dbPath.replace(/'/g, \"''\")\n // Attach the project DuckDB file in read-only mode and make it the active schema\n await this.connection.run(`attach '${escapedPath}' as graphene_cli (READ_ONLY);`)\n await this.connection.run('use graphene_cli;')\n }\n\n async runQuery(sql: string, params?: QueryParams): Promise<QueryResult> {\n await this.ready\n let reader = params ? await this.connection!.runAndReadAll(sql, params as any) : await this.connection!.runAndReadAll(sql)\n let rows = reader.getRowObjects().map(record => {\n let out: Record<string, unknown> = {}\n for (let [k, v] of Object.entries(record)) {\n if (typeof v === 'bigint') out[k] = Number(v)\n else if (v === null) out[k] = null\n else if (v instanceof DuckDBTimestampValue) out[k] = new Date(Number(v.micros / 1000n)).toUTCString()\n else if (v instanceof DuckDBDateValue) out[k] = v.toString()\n else if (v instanceof DuckDBDecimalValue) out[k] = v.toDouble()\n else if (typeof v === 'object') throw new Error(`Unsupported datatype ${v.constructor?.name}`)\n else out[k] = v\n }\n return out\n })\n return {rows}\n }\n\n async listDatasets(): Promise<string[]> {\n return await Promise.resolve([])\n }\n\n async listTables(): Promise<string[]> {\n let sql = `\n select table_schema as table_schema, table_name as table_name\n from information_schema.tables\n where table_type in ('BASE TABLE', 'VIEW') and table_schema not in ('information_schema', 'pg_catalog')\n order by table_schema, table_name\n `.trim()\n let res = await this.runQuery(sql)\n return res.rows.map(row => String(row['table_name']).toLowerCase())\n }\n\n async describeTable(target: string): Promise<SchemaColumn[]> {\n let parts = target.split('.')\n let table = parts.pop() || ''\n let schema = parts[0]\n let schemaFilter = schema ? 'lower(table_schema) = lower($2)' : \"table_schema not in ('information_schema', 'pg_catalog')\"\n let sql = `\n select column_name as column_name, data_type as data_type, ordinal_position as ordinal_position\n from information_schema.columns\n where lower(table_name) = lower($1) and ${schemaFilter}\n order by ordinal_position\n `.trim()\n let params = schema ? [table, schema] : [table]\n let res = await this.runQuery(sql, params)\n return res.rows.map(row => {\n return {name: String(row['column_name']).toLowerCase(), dataType: String(row['data_type'])}\n })\n }\n\n async close(): Promise<void> {\n await this.ready\n this.connection?.closeSync()\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,447 @@
1
+ import {
2
+ analyzeWorkspace,
3
+ getWorkspaceScanCounts,
4
+ loadWorkspace,
5
+ mockFileMap,
6
+ runQuery,
7
+ runVitePlugin,
8
+ toSql
9
+ } from "./chunk-OVWODUTJ.js";
10
+ import {
11
+ config
12
+ } from "./chunk-QAXEOZ43.js";
13
+
14
+ // serve2.ts
15
+ import { svelte, vitePreprocess } from "@sveltejs/vite-plugin-svelte";
16
+ import crypto from "crypto";
17
+ import fs2 from "fs-extra";
18
+ import { mdsvex } from "mdsvex";
19
+ import { createRequire } from "module";
20
+ import path2 from "path";
21
+ import { fileURLToPath } from "url";
22
+ import { createServer, optimizeDeps, resolveConfig } from "vite";
23
+
24
+ // mdCompile.ts
25
+ import { decodeHTML } from "entities";
26
+ import fs from "fs";
27
+ import yaml from "js-yaml";
28
+ import JSON5 from "json5";
29
+ import path from "path";
30
+ import sanitizeHtml from "sanitize-html";
31
+ import { visit } from "unist-util-visit";
32
+ function escapeHtml(str) {
33
+ return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
34
+ }
35
+ function liftInlineEChartsConfig(content) {
36
+ return content.replace(/<ECharts\b([^>]*)>([\s\S]*?)<\/ECharts>/g, (match, attrs = "", body = "") => {
37
+ let inline = body.trim();
38
+ if (!inline) return match;
39
+ if (/\sconfig\s*=/.test(attrs)) return match;
40
+ let source = inline.startsWith("{") ? inline : `{${inline}}`;
41
+ let config2 = JSON.stringify(JSON5.parse(source), (_key, value) => typeof value == "string" ? decodeHTML(value) : value);
42
+ return `<ECharts${attrs} config={${config2}}></ECharts>`;
43
+ });
44
+ }
45
+ function extractQueries() {
46
+ return function transformer(tree) {
47
+ visit(tree, "code", (node, index, parent) => {
48
+ if (index === null) return;
49
+ let name = typeof node.meta === "string" ? node.meta : "";
50
+ let code = typeof node.value === "string" ? node.value.trim() : "";
51
+ parent.children[index] = { type: "html", value: `<GrapheneQuery name="${escapeHtml(name)}" code="${escapeHtml(code)}" />` };
52
+ });
53
+ };
54
+ }
55
+ function escapeAngles() {
56
+ return function transformer(tree) {
57
+ visit(tree, "text", (node) => {
58
+ if (!node.value || typeof node.value !== "string") return;
59
+ if (!node.value.includes("<")) return;
60
+ node.value = node.value.replace(/</g, "&lt;");
61
+ });
62
+ };
63
+ }
64
+ function mergeAdjacentHtml() {
65
+ return function transformer(tree) {
66
+ visit(tree, (parent) => {
67
+ if (!Array.isArray(parent?.children)) return;
68
+ for (let i = 0; i < parent.children.length; i++) {
69
+ if (parent.children[i]?.type !== "html") continue;
70
+ let j = i;
71
+ while (j + 1 < parent.children.length && parent.children[j + 1]?.type === "html") j++;
72
+ if (j == i) continue;
73
+ let value = parent.children.slice(i, j + 1).map((node) => node.value || "").join("\n");
74
+ parent.children.splice(i, j - i + 1, { type: "html", value });
75
+ }
76
+ });
77
+ };
78
+ }
79
+ function sanitizeMarkdown() {
80
+ return function transformer(tree) {
81
+ visit(tree, "raw", (node) => {
82
+ if (typeof node.value !== "string") return;
83
+ let expanded = node.value.replace(/<(\w+)((?:\s[^<>]*?)?)\s*\/>/gi, (_, name, attrs = "") => {
84
+ let spacing = attrs;
85
+ return `<${name}${spacing}></${name}>`;
86
+ });
87
+ let sanitized = sanitizeHtml(expanded, {
88
+ ...sanitizeHtml.defaults,
89
+ allowedTags: [...sanitizeHtml.defaults.allowedTags, ...componentNames()],
90
+ allowedAttributes: {
91
+ ...sanitizeHtml.defaults.allowedAttributes,
92
+ ...Object.fromEntries(componentNames().map((n) => [n, ["*"]]))
93
+ },
94
+ parser: {
95
+ ...sanitizeHtml.defaults.parser || {},
96
+ lowerCaseAttributeNames: false,
97
+ lowerCaseTags: false
98
+ }
99
+ });
100
+ node.value = sanitized;
101
+ });
102
+ };
103
+ }
104
+ function injectComponentImports() {
105
+ let imp = `const {${componentNames().join(", ")}} = window.$GRAPHENE.components`;
106
+ return {
107
+ markup: ({ content, filename }) => {
108
+ if (!filename.endsWith(".md")) return;
109
+ content = liftInlineEChartsConfig(content);
110
+ if (content.includes("<script>")) {
111
+ content = content.replace("<script>", `<script>
112
+ ${imp}`);
113
+ } else {
114
+ content = `<script>
115
+ ${imp}
116
+ </script>
117
+ ${content}`;
118
+ }
119
+ return { code: content };
120
+ },
121
+ style: () => {
122
+ },
123
+ script: () => {
124
+ }
125
+ };
126
+ }
127
+ var cachedComponentNames = null;
128
+ function componentNames() {
129
+ if (cachedComponentNames) return cachedComponentNames;
130
+ let files = fs.readdirSync(path.join(import.meta.dirname, "../ui/components"));
131
+ cachedComponentNames = files.map((f) => path.basename(f, ".svelte")).filter((f) => !f.startsWith("_"));
132
+ return cachedComponentNames || [];
133
+ }
134
+ var frontmatterRe = /^---\s*\n([\s\S]*?)\n---(?:\n|$)/;
135
+ function extractFrontmatter(contents) {
136
+ let match = contents.trimStart().match(frontmatterRe);
137
+ if (!match) return {};
138
+ let raw = yaml.safeLoad(match[1]);
139
+ return { title: raw?.title ? String(raw.title) : void 0 };
140
+ }
141
+ var remarkPlugins = [extractQueries, escapeAngles, mergeAdjacentHtml];
142
+ var rehypePlugins = [sanitizeMarkdown];
143
+
144
+ // serve2.ts
145
+ var svelteWarnings = [];
146
+ function clearSvelteWarnings() {
147
+ svelteWarnings.length = 0;
148
+ }
149
+ var QUERY_VERSION = 1;
150
+ var uiRoot;
151
+ var nodeRequire = createRequire(import.meta.url);
152
+ async function serve2(telemetry) {
153
+ let server = await createServer(await createConfig(telemetry));
154
+ await server.listen();
155
+ console.log(`Server running at http://localhost:${server.config.server.port}`);
156
+ return server;
157
+ }
158
+ async function createConfig(telemetry) {
159
+ uiRoot = path2.join(fileURLToPath(import.meta.url), "../../ui");
160
+ let port = Number(process.env.GRAPHENE_PORT) || 4e3;
161
+ let svelteRoot = path2.dirname(nodeRequire.resolve("svelte/package.json"));
162
+ let sveltePackage = nodeRequire("svelte/package.json");
163
+ let svelteDependencyRoot = path2.dirname(svelteRoot);
164
+ let svelteExport = (name) => path2.join(svelteRoot, sveltePackage.exports[name].browser || sveltePackage.exports[name].default);
165
+ let packaged = path2.basename(path2.dirname(uiRoot)) == "dist";
166
+ await fs2.ensureDir(path2.resolve(config.root, "node_modules/.graphene"));
167
+ let inContainer = fs2.existsSync("/.dockerenv");
168
+ let host = inContainer ? "0.0.0.0" : "127.0.0.1";
169
+ return {
170
+ root: config.root,
171
+ logLevel: process.env.NODE_ENV == "test" ? "silent" : "info",
172
+ plugins: [
173
+ svelte({
174
+ configFile: false,
175
+ extensions: [".svelte", ".md"],
176
+ preprocess: [
177
+ vitePreprocess(),
178
+ mdsvex({
179
+ extensions: [".md"],
180
+ remarkPlugins,
181
+ rehypePlugins
182
+ }),
183
+ injectComponentImports()
184
+ ],
185
+ onwarn(warning, defaultHandler) {
186
+ if (process.env.NODE_ENV === "test") {
187
+ svelteWarnings.push({ code: warning.code, message: warning.message, filename: warning.filename });
188
+ }
189
+ defaultHandler?.(warning);
190
+ }
191
+ }),
192
+ fixSvelteDepsInTests(),
193
+ fixHmrForFailedModules(),
194
+ runVitePlugin(),
195
+ handleRequestPlugin,
196
+ updateWorkspacePlugin(telemetry),
197
+ mockFilesForTests()
198
+ ],
199
+ publicDir: path2.resolve(uiRoot, "public"),
200
+ // on the fence about this one. This would make it less likely we need to optimize when alternating between dev and tests.
201
+ // cacheDir: process.env.NODE_ENV == 'test' ? 'node_modules/.vite-tests' : 'node_modules/.vite',
202
+ server: {
203
+ port,
204
+ host,
205
+ fs: { strict: false },
206
+ strictPort: true,
207
+ hmr: { overlay: false }
208
+ // we handle compilation errors ourselves (see LocalApp.svelte)
209
+ },
210
+ resolve: {
211
+ alias: [
212
+ { find: /^graphene$/, replacement: path2.resolve(uiRoot, "web.js") },
213
+ // Vite runs in a user project, but svelte is a direct dependency of the cli, and thus transitive to the user project.
214
+ // So when Vite tries to resolve `svelte` from a compiled md page, it can't find it without these aliases.
215
+ { find: /^svelte$/, replacement: svelteExport(".") },
216
+ { find: /^svelte\/animate$/, replacement: svelteExport("./animate") },
217
+ { find: /^svelte\/attachments$/, replacement: svelteExport("./attachments") },
218
+ { find: /^svelte\/easing$/, replacement: svelteExport("./easing") },
219
+ { find: /^svelte\/events$/, replacement: svelteExport("./events") },
220
+ { find: /^svelte\/internal$/, replacement: svelteExport("./internal") },
221
+ { find: /^svelte\/internal\/client$/, replacement: svelteExport("./internal/client") },
222
+ { find: /^svelte\/internal\/disclose-version$/, replacement: svelteExport("./internal/disclose-version") },
223
+ { find: /^svelte\/internal\/flags\/async$/, replacement: svelteExport("./internal/flags/async") },
224
+ { find: /^svelte\/internal\/flags\/legacy$/, replacement: svelteExport("./internal/flags/legacy") },
225
+ { find: /^svelte\/internal\/flags\/tracing$/, replacement: svelteExport("./internal/flags/tracing") },
226
+ { find: /^svelte\/legacy$/, replacement: svelteExport("./legacy") },
227
+ { find: /^svelte\/motion$/, replacement: svelteExport("./motion") },
228
+ { find: /^svelte\/reactivity$/, replacement: svelteExport("./reactivity") },
229
+ { find: /^svelte\/reactivity\/window$/, replacement: svelteExport("./reactivity/window") },
230
+ { find: /^svelte\/store$/, replacement: svelteExport("./store") },
231
+ { find: /^svelte\/transition$/, replacement: svelteExport("./transition") },
232
+ { find: /^clsx$/, replacement: path2.join(svelteDependencyRoot, "clsx/dist/clsx.mjs") }
233
+ ]
234
+ },
235
+ optimizeDeps: {
236
+ noDiscovery: process.env.NODE_ENV == "test",
237
+ // tests manually optimize before starting test workers
238
+ exclude: ["virtual:nav"],
239
+ // provided by a plugin, so don't try and optimize it
240
+ // Vite running in a user project will not naturally discover and optimize these transitive deps.
241
+ // When you launch the server, your first page load will automatically refresh after a second or two as Vite now sees and optimizes these.
242
+ // This line makes it do that up-front, avoiding that reload jank. The packaged CLI also pre-bundles the `graphene` alias itself;
243
+ // doing that from source causes trouble in examples/tests because the alias points outside node_modules.
244
+ // `graphene` here is a special case: when packaged up it is considered a dependency, but in examples/tests, including it would cause errors.
245
+ // oxfmt-ignore
246
+ include: [
247
+ ...packaged ? ["graphene"] : [],
248
+ "@graphenedata/cli > svelte",
249
+ "@graphenedata/cli > chroma-js",
250
+ "@graphenedata/cli > echarts",
251
+ "@graphenedata/cli > @graphenedata/html2canvas",
252
+ "@graphenedata/cli > @graphenedata/ui > svelte",
253
+ "@graphenedata/cli > @graphenedata/ui > chroma-js",
254
+ "@graphenedata/cli > @graphenedata/ui > echarts/dist/echarts.esm.js",
255
+ "@graphenedata/cli > @graphenedata/ui > @graphenedata/html2canvas"
256
+ ]
257
+ }
258
+ };
259
+ }
260
+ async function handleQuery(req, res) {
261
+ let chunks = [];
262
+ for await (let chunk of req) chunks.push(chunk);
263
+ let { gsql, params, hashes } = JSON.parse(Buffer.concat(chunks).toString());
264
+ res.setHeader("Content-Type", "application/json");
265
+ await workspaceLoadPromise;
266
+ let gsqlFiles = workspaceFiles.filter((file) => !file.path.endsWith(".md"));
267
+ let result = analyzeWorkspace({ config, files: [...gsqlFiles, { path: "input", contents: gsql }] });
268
+ updateParsedFiles(result);
269
+ let diagnostics = result.diagnostics;
270
+ if (diagnostics.length) {
271
+ res.statusCode = 400;
272
+ res.end(JSON.stringify(diagnostics[0]));
273
+ return;
274
+ }
275
+ let queries = result.files.find((file) => file.path == "input")?.queries || [];
276
+ if (queries.length > 1) throw new Error("Found multiple queries, which could be a parsing error");
277
+ let sql = toSql(queries[0], params);
278
+ let hash = crypto.createHash("SHA1").update(`query-v${QUERY_VERSION}|${sql}`).digest("hex");
279
+ res.setHeader("ETag", hash);
280
+ if (hashes.includes(hash) && req.headers["cache-control"] != "no-cache") {
281
+ res.statusCode = 304;
282
+ return res.end();
283
+ }
284
+ let queryResults = await runQuery(sql);
285
+ let totalRows = queryResults.totalRows ?? queryResults.rows.length;
286
+ if (totalRows > queryResults.rows.length) throw new Error("Query returns too many rows");
287
+ let fields = queries[0].fields.map((field) => ({ name: field.name, type: field.type, metadata: field.metadata || {} }));
288
+ res.end(JSON.stringify({ rows: queryResults.rows, hash, fields, sql }));
289
+ }
290
+ async function handlePage(server, res) {
291
+ res.setHeader("Content-Type", "text/html");
292
+ let html = await server.transformIndexHtml(
293
+ "/index.html",
294
+ `<!doctype html>
295
+ <html lang="en">
296
+ <head>
297
+ <meta charset="UTF-8" />
298
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
299
+ <title>Graphene</title>
300
+ <link rel="icon" href="/favicon.ico" />
301
+ </head>
302
+ <body>
303
+ <script type="module">
304
+ import 'graphene'
305
+ </script>
306
+ </body>
307
+ </html>`
308
+ );
309
+ return res.end(html);
310
+ }
311
+ async function prepareDeps() {
312
+ let cfg = await resolveConfig(await createConfig(), "serve");
313
+ await optimizeDeps(cfg, true);
314
+ }
315
+ function fixSvelteDepsInTests() {
316
+ let viteConfig;
317
+ function configResolved(cfg) {
318
+ viteConfig = cfg;
319
+ }
320
+ function buildStart() {
321
+ if (process.env.NODE_ENV != "test") return;
322
+ viteConfig.optimizeDeps.force = false;
323
+ }
324
+ buildStart.sequential = true;
325
+ return { name: "fix-svelte-deps", enforce: "post", configResolved, buildStart };
326
+ }
327
+ function fixHmrForFailedModules() {
328
+ return {
329
+ name: "fix-hmr-for-failed-modules",
330
+ hotUpdate({ modules }) {
331
+ let hasFailed = modules.some((m) => !m.transformResult);
332
+ if (hasFailed) {
333
+ this.environment.hot.send({ type: "full-reload", path: "*" });
334
+ return [];
335
+ }
336
+ }
337
+ };
338
+ }
339
+ var workspaceLoadPromise;
340
+ var workspaceFiles = [];
341
+ var mdFiles = [];
342
+ function updateWorkspacePlugin(telemetry) {
343
+ return {
344
+ name: "updateWorkspace",
345
+ resolveId(id) {
346
+ if (id == "virtual:nav") return "\0virtual:nav";
347
+ },
348
+ load(id) {
349
+ if (id != "\0virtual:nav") return;
350
+ let res = [...mdFiles];
351
+ if (process.env.NODE_ENV == "test") {
352
+ for (let [path3, contents] of Object.entries(mockFileMap)) {
353
+ let mockFile = { path: path3, title: extractFrontmatter(contents).title };
354
+ let idx = res.findIndex((file) => file.path == path3);
355
+ if (idx >= 0) res.splice(idx, 1, mockFile);
356
+ else res.push(mockFile);
357
+ }
358
+ }
359
+ return `export default ${JSON.stringify(res)}`;
360
+ },
361
+ configureServer: (s) => {
362
+ let refresh = async () => {
363
+ workspaceLoadPromise = (async () => {
364
+ let loaded = await loadWorkspace(config.root, true, config.ignoredFiles);
365
+ telemetry?.event("workspace_scanned", { command: "serve", ...getWorkspaceScanCounts(loaded) });
366
+ workspaceFiles = loaded.map((file) => {
367
+ let existing = workspaceFiles.find((existing2) => existing2.path == file.path && existing2.contents == file.contents);
368
+ return existing?.parsed ? { ...file, parsed: existing.parsed } : file;
369
+ });
370
+ })();
371
+ await workspaceLoadPromise;
372
+ mdFiles = workspaceFiles.filter((file) => file.path.endsWith(".md")).map((f) => ({ path: f.path, title: extractFrontmatter(f.contents).title }));
373
+ let mod = s.moduleGraph.getModuleById("\0virtual:nav");
374
+ if (!mod) return;
375
+ s.reloadModule(mod);
376
+ };
377
+ s.watcher.add(["**/*.gsql", "**/*.md"]);
378
+ s.watcher.on("all", refresh);
379
+ refresh();
380
+ }
381
+ };
382
+ }
383
+ function updateParsedFiles(analysis) {
384
+ workspaceFiles = workspaceFiles.map((file) => {
385
+ let analyzed = analysis.files.find((next) => next.path == file.path);
386
+ if (!analyzed) return file;
387
+ return {
388
+ ...file,
389
+ parsed: {
390
+ tree: analyzed.tree,
391
+ virtualContents: analyzed.virtualContents,
392
+ virtualToMarkdownOffset: analyzed.virtualToMarkdownOffset
393
+ }
394
+ };
395
+ });
396
+ }
397
+ var handleRequestPlugin = {
398
+ name: "handleRequest",
399
+ configureServer: (s) => {
400
+ s.middlewares.use(async function handleRequest(req, res, next) {
401
+ try {
402
+ let [pathName] = (req.url || "").split("?");
403
+ if (pathName == "/_api/query") return await handleQuery(req, res);
404
+ if (pathName) {
405
+ if (pathName == "/__ct" || pathName == "/_charts" || pathName == "/_styles") return await handlePage(s, res);
406
+ }
407
+ if (!pathName || pathName == "/") pathName = "index";
408
+ let relativeMdPath = pathName.replace(/^\//, "") + ".md";
409
+ let mdPath = path2.join(config.root, relativeMdPath);
410
+ if (mockFileMap[relativeMdPath] || await fs2.exists(mdPath)) {
411
+ await handlePage(s, res);
412
+ } else {
413
+ next();
414
+ }
415
+ } catch (err) {
416
+ if (process.env.NODE_ENV != "test") console.error(err);
417
+ res.statusCode = 500;
418
+ res.end(JSON.stringify({ message: err.message, stack: err.stack }));
419
+ }
420
+ });
421
+ }
422
+ };
423
+ function mockFilesForTests() {
424
+ if (process.env.NODE_ENV !== "test") return null;
425
+ function toMockKey(id) {
426
+ return id.replace(config.root + "/", "").replace(/^\//, "");
427
+ }
428
+ return {
429
+ name: "mock-files-for-tests",
430
+ enforce: "pre",
431
+ resolveId(id) {
432
+ if (!mockFileMap[toMockKey(id)]) return;
433
+ return path2.join(config.root, toMockKey(id)) + "?mock";
434
+ },
435
+ load(id) {
436
+ if (!id.endsWith("?mock")) return null;
437
+ return mockFileMap[toMockKey(id.replace(/\?mock$/, ""))];
438
+ }
439
+ };
440
+ }
441
+ export {
442
+ clearSvelteWarnings,
443
+ prepareDeps,
444
+ serve2,
445
+ svelteWarnings
446
+ };
447
+ //# sourceMappingURL=serve2-TNN5EROW.js.map