@graphenedata/cli 0.0.11 → 0.0.13
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/bin.js +15 -0
- package/dist/cli/cli.js +49 -39
- package/dist/docs/graphene.md +1 -3
- package/dist/ui/components/_Table.svelte +16 -13
- package/package.json +4 -3
- package/cli.ts +0 -156
package/bin.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {fileURLToPath} from 'url'
|
|
4
|
+
import {dirname, join} from 'path'
|
|
5
|
+
import {existsSync} from 'fs'
|
|
6
|
+
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const devCli = join(__dirname, 'cli.ts')
|
|
9
|
+
|
|
10
|
+
// If Graphene has been npm-linked in, we can run cli.ts directly to avoid the build step
|
|
11
|
+
if (existsSync(devCli)) {
|
|
12
|
+
await import('./cli.ts')
|
|
13
|
+
} else {
|
|
14
|
+
await import('./dist/cli/cli.js')
|
|
15
|
+
}
|
package/dist/cli/cli.js
CHANGED
|
@@ -720,7 +720,7 @@ function makeTable(name, type) {
|
|
|
720
720
|
return { name, type, fields: [], connection: config.dialect, dialect: config.dialect, tableName: name, tablePath, metadata: {} };
|
|
721
721
|
}
|
|
722
722
|
function addColumnField(table2, node) {
|
|
723
|
-
let name = txt(node.getChild("
|
|
723
|
+
let name = txt(node.getChild("ColumnName"));
|
|
724
724
|
if (node.getChild("PrimaryKey")) {
|
|
725
725
|
if (table2.primaryKey) diag(node, `Table ${table2.name} has multiple primary keys`);
|
|
726
726
|
table2.primaryKey = name;
|
|
@@ -1077,6 +1077,8 @@ function analyzeTimeExpression(op, left2, right2, node) {
|
|
|
1077
1077
|
function ensureSameType(left2, leftNode, right2, rightNode) {
|
|
1078
1078
|
if (left2.type === "error" || right2.type === "error") return;
|
|
1079
1079
|
if (left2.node === "parameter" || right2.node === "parameter") return;
|
|
1080
|
+
if (left2.type === "date" || left2.type === "timestamp") checkTypes(right2, [left2.type], rightNode);
|
|
1081
|
+
if (right2.type === "date" || right2.type === "timestamp") checkTypes(left2, [right2.type], leftNode);
|
|
1080
1082
|
if (left2.type !== right2.type) diag(rightNode, `Expected ${left2.type}, got ${right2.type}`);
|
|
1081
1083
|
}
|
|
1082
1084
|
function checkTypes(expr, expected, node) {
|
|
@@ -1084,6 +1086,14 @@ function checkTypes(expr, expected, node) {
|
|
|
1084
1086
|
if (expr.node === "parameter") return;
|
|
1085
1087
|
if (expected.includes(expr.type)) return;
|
|
1086
1088
|
if (expected.includes("generic")) return;
|
|
1089
|
+
let dt = expected.find((t) => t == "date") || expected.find((t) => t == "timestamp");
|
|
1090
|
+
if (expr.node == "stringLiteral" && dt) {
|
|
1091
|
+
let parsed = parseTemporalLiteral(expr.literal, dt);
|
|
1092
|
+
if (!parsed) return diag(node, `Could not parse ${dt} literal: "${expr.literal}"`, void 0);
|
|
1093
|
+
let typeDef = { type: parsed.type, timeframe: parsed.timeframe };
|
|
1094
|
+
Object.assign(expr, { node: "timeLiteral", literal: parsed?.literal, type: parsed?.type, typeDef });
|
|
1095
|
+
return;
|
|
1096
|
+
}
|
|
1087
1097
|
diag(node, `Expected types: ${expected.join(", ")}`);
|
|
1088
1098
|
}
|
|
1089
1099
|
function lookupField(expr, scope) {
|
|
@@ -1250,35 +1260,35 @@ var init_parser_terms = __esm({
|
|
|
1250
1260
|
date = 10;
|
|
1251
1261
|
timestamp = 12;
|
|
1252
1262
|
interval = 14;
|
|
1253
|
-
primary_key =
|
|
1254
|
-
join =
|
|
1255
|
-
as =
|
|
1256
|
-
on =
|
|
1257
|
-
or =
|
|
1258
|
-
and =
|
|
1259
|
-
like =
|
|
1260
|
-
not =
|
|
1261
|
-
_in =
|
|
1262
|
-
from =
|
|
1263
|
-
inner =
|
|
1264
|
-
left =
|
|
1265
|
-
right =
|
|
1266
|
-
full =
|
|
1267
|
-
cross =
|
|
1268
|
-
select =
|
|
1269
|
-
where =
|
|
1270
|
-
group =
|
|
1271
|
-
by =
|
|
1272
|
-
order =
|
|
1273
|
-
asc =
|
|
1274
|
-
desc =
|
|
1275
|
-
limit =
|
|
1276
|
-
offset =
|
|
1277
|
-
is =
|
|
1278
|
-
_null =
|
|
1279
|
-
exists =
|
|
1280
|
-
_true =
|
|
1281
|
-
_false =
|
|
1263
|
+
primary_key = 18;
|
|
1264
|
+
join = 22;
|
|
1265
|
+
as = 28;
|
|
1266
|
+
on = 31;
|
|
1267
|
+
or = 40;
|
|
1268
|
+
and = 44;
|
|
1269
|
+
like = 53;
|
|
1270
|
+
not = 55;
|
|
1271
|
+
_in = 65;
|
|
1272
|
+
from = 70;
|
|
1273
|
+
inner = 76;
|
|
1274
|
+
left = 78;
|
|
1275
|
+
right = 80;
|
|
1276
|
+
full = 82;
|
|
1277
|
+
cross = 84;
|
|
1278
|
+
select = 87;
|
|
1279
|
+
where = 94;
|
|
1280
|
+
group = 97;
|
|
1281
|
+
by = 99;
|
|
1282
|
+
order = 105;
|
|
1283
|
+
asc = 109;
|
|
1284
|
+
desc = 111;
|
|
1285
|
+
limit = 114;
|
|
1286
|
+
offset = 116;
|
|
1287
|
+
is = 119;
|
|
1288
|
+
_null = 121;
|
|
1289
|
+
exists = 139;
|
|
1290
|
+
_true = 143;
|
|
1291
|
+
_false = 145;
|
|
1282
1292
|
}
|
|
1283
1293
|
});
|
|
1284
1294
|
|
|
@@ -1337,24 +1347,24 @@ var init_parser = __esm({
|
|
|
1337
1347
|
"../lang/parser.js"() {
|
|
1338
1348
|
"use strict";
|
|
1339
1349
|
init_tokens();
|
|
1340
|
-
spec_Identifier = { __proto__: null, table: 10, date: 20, timestamp: 24, interval: 28, primary_key:
|
|
1350
|
+
spec_Identifier = { __proto__: null, table: 10, date: 20, timestamp: 24, interval: 28, primary_key: 36, join: 44, one: 48, many: 52, as: 56, on: 62, or: 80, and: 88, like: 106, not: 110, in: 130, from: 140, inner: 152, left: 156, right: 160, full: 164, cross: 168, select: 174, distinct: 178, where: 188, group: 194, by: 198, having: 204, order: 210, asc: 218, desc: 222, limit: 228, offset: 232, is: 238, null: 242, case: 252, when: 258, then: 262, else: 268, end: 272, exists: 278, true: 286, false: 290, count: 300, extract: 306, cast: 314, extend: 340 };
|
|
1341
1351
|
parser = LRParser.deserialize({
|
|
1342
1352
|
version: 14,
|
|
1343
|
-
states: "
|
|
1344
|
-
stateData: "!
|
|
1345
|
-
goto: "!
|
|
1346
|
-
nodeNames: "\u26A0 Program TableStatement Kw Identifier table Ref ColumnDef
|
|
1347
|
-
maxTerm:
|
|
1353
|
+
states: "KOQYQPOOOOQO'#C_'#C_OOQO'#Ds'#DsOwQPO'#DrOOQO'#EU'#EUO#aQPO'#ETOOQO'#E]'#E]OOQO'#E`'#E`O#hQPO'#E_OOQO'#Ee'#EeOOQO'#Eh'#EhO#hQPO'#EgOOQO'#Eq'#EqO#mQPO'#EpOOQO'#GR'#GRO$ZQPO'#DqO$hQPO'#C^OOQO'#F{'#F{O$hQPO'#FzO$mQPO'#F}QYQPOOQ%bQPO'#F}O%gQPO'#E[O%gQPO'#EdO)^QPO'#CbO)hQPO'#CbO)mQPO'#DuO#rQPO'#DwO*zQPO'#DvOOQO'#Gc'#GcO,mQPO,5:^O-aQPO'#CbO.sQPO'#CbOOQO'#Ce'#CeOOQO'#Cg'#CgOOQO'#Ci'#CiO0]QPO'#EYOOQO'#Dd'#DdO1VQPO'#DwOOQO'#EW'#EWOOQO'#EZ'#EZOOQO'#EY'#EYO1pQPO,5:oO!PQPO,5:oOOQO'#Ex'#ExOOQO'#E{'#E{OOQO'#E}'#E}O2eQPO'#E|OOQO'#F['#F[O2lQPO'#FZOOQO'#F`'#F`OOQO'#Fb'#FbOOQO'#F_'#F_OOQO'#Fd'#FdOOQO'#Gg'#GgOOQO'#Fg'#FgO2qQPO'#FfOOQO'#Gf'#GfOOQO'#Fj'#FjOOQO'#Fn'#FnO2vQPO'#FpO3OQPO'#FrO3TQPO'#FsOOQO'#Ge'#GeOOQO'#Gh'#GhOOQO'#Ga'#GaO%gQPO'#EzO3YQPO'#FiO3_QPO'#FmOOQO'#Eb'#EbO!PQPO,5:yO3dQPO,5;RO3lQPO,5;[OOQO-E:P-E:PO4aQPO,58xO4iQPO,5<fOOQO,5<i,5<iOOQO-E9{-E9{O4nQPO,5:vO5bQPO,5;OOOQO,5<j,5<jO6UQPO,58|OOQO-E9|-E9|OOQO'#Cw'#CwOOQO'#Cy'#CyOOQO,5:a,5:aO:PQPO,5:aO:UQPO,5:cOOQO,5:b,5:bO:PQPO,5:bOOQO'#Cq'#CqOOQO'#Dy'#DyOOQO'#D{'#D{OOQO'#D}'#D}OOQO'#EP'#EPOOQO'#ER'#EROwQPO'#DxO:ZQPO'#DxOOQO'#GS'#GSO:`QPO1G/xO;SQPO,5<POOQO,5:u,5:uOOQO'#DT'#DTO;ZQPO,59qOOQO'#DX'#DXOOQO'#Db'#DbOOQO'#DZ'#DZO;iQPO,5:XOOQO'#Df'#DfOOQO'#Di'#DiOOQO'#Dn'#DnO;qQPO,5:XOOQO'#Ev'#EvO;vQPO,5;aO%gQPO,59rO%gQPO,59rO%gQPO,59rO%gQPO,59rO%gQPO,59rOOQO,5:t,5:tO:PQPO,5:tO<OQPO,5<aO<VQPO1G0ZO<yQPO1G0ZO<yQPO1G0ZO=nQPO,5;hOOQO'#FQ'#FQOOQO'#GV'#GVO=uQPO,5;hO%gQPO'#FPO#rQPO,5;uO>QQPO,5<QOOQO,5<[,5<[O>_QPO,5<[OOQO,5<^,5<^OOQO,5<_,5<_O>dQPO,5;fOBUQPO,5<TO%gQPO,5<XOB^QPO1G0eOCRQPO'#EjOC|QPO1G0mOOQO'#Es'#EsODqQPO1G0vODvQPO1G.dOFTQPO1G2POFYQPO1G2QPGgQPO'#GOOOQO1G/{1G/{OOQO1G/}1G/}OOQO1G/|1G/|OGlQPO,5:dOwQPO,5:dOOQO-E:Q-E:QOHsQPO1G1kOOQO1G1k1G1kOOQO'#DR'#DROOQO1G/]1G/]OOQO,59u,59uOH}QPO1G/sO1VQPO1G/sOOQO1G0{1G0{O;yQPO1G0{OLqQPO1G/^OLxQPO1G/^O!!kQPO1G/^O!!uQPO1G/^O!#PQPO1G/^OOQO1G0`1G0`OOQO1G1{1G1{OOQO,5<o,5<oO!&qQPO7+%uOOQO-E:R-E:RO!'eQPO7+%uO=uQPO1G1SOOQO-E:T-E:TOOQO'#FV'#FVOOQO'#FX'#FXOOQO1G1S1G1SO={QPO1G1SO%gQPO'#FUO!(YQPO,5;kO!(aQPO1G1aO!(fQPO1G1lOOQO1G1l1G1lO!(mQPO1G1lO%gQPO1G1lOOQO'#Fq'#FqOOQO1G1v1G1vOOQO'#Fl'#FlO!(rQPO1G1oO.{QPO1G1sO!(wQPO7+&PO!)kQPO7+&POOQO'#El'#ElOOQO'#En'#EnOOQO,5;U,5;UO!+QQPO7+&XO!+[QPO7+&XOOQO7+&b7+&bO!,|QPO'#CbO!-^QPO'#CdO!-oQPO'#CdO!.QQPO'#CdO!.fQPO'#CcO!.tQPO'#CpO$hQPO'#CoO!0WQPO'#DOOOQO'#G`'#G`OOQO'#G_'#G_O!0bQPO'#GPO!1uQPO7+$OO!1|QPO'#DOO#rQPO7+'kO!+cQPO'#CbOOQO'#Gj'#GjO!2RQPO'#GWO!3fQPO7+'lOOQO'#Cz'#CzO%gQPO1G0OO!3mQPO1G0OO!4tQPO7+'VO!4|QPO7+'VOOQO7+'V7+'VO1VQPO7+%_O!5TQPO'#DpO!5_QPO7+%_OOQO7+&g7+&gP!PQPO'#GTO!5dQPO<<IaOOQO7+&n7+&nO={QPO7+&nO!6WQPO,5;pOOQO'#FS'#FSO%gQPO1G1VOOQO7+&{7+&{OOQO7+'W7+'WO!6_QPO7+'WO%gQPO7+'ZO;ZQPO7+'_O!6fQPO<<IkOOQO,5<p,5<pO!7YQPO<<IsOOQO-E:S-E:SOOQO'#Ck'#CkO!8QQPO,58}OOQO'#Cs'#CsOOQO'#Cu'#CuOOQO,59[,59[O!9hQPO,59ZO;ZQPO,59kO;iQPO,5<bO!9pQPO,5<bO;vQPO,5<cO%gQPO,59nO%gQPO,59nO%gQPO,59nO%gQPO,59nO%gQPO,59nO:PQPO,59jOOQO,5<k,5<kOOQO-E9}-E9}OOQO<<Gj<<GjO%gQPO,59jO!9uQPO<<KVOOQO,5<r,5<rOOQO-E:U-E:UOOQO<<KW<<KWO!9zQPO7+%jO%gQPO7+%jOOQO-E:O-E:OO!;QQPO<<JqOOQO<<Jq<<JqO!;XQPO,5<lO!;cQPO<<HyO!;hQPO,5:[O!;pQPO,5:[OOQO<<Hy<<HyOOQO<<JY<<JYO!;wQPO7+&qOOQO<<Jr<<JrO!<UQPO<<JuO!<]QPO<<JyP3dQPO'#GUOOQO'#Cm'#CmOOQO'#Cl'#ClOOQO1G.i1G.iO$hQPO1G.uO:PQPO1G.uOOQO1G/V1G/VO!<bQPO1G1|O1VQPO1G1|OOQO1G1}1G1}O;yQPO1G1}O!=tQPO1G/YO!={QPO1G/YO!?^QPO1G/YO!?hQPO1G/YO!?rQPO1G/YOOQO1G/U1G/UO!ASQPO1G/UOOQOAN@qAN@qO!B`QPO<<IUP%gQPO'#GQOOQOAN@]AN@]OOQOAN>eAN>eO!CfQPO1G/vOOQOAN@aAN@aOOQOAN@eAN@eO!CmQPO'#C|OOQO7+$a7+$aO!9kQPO7+$aO1VQPO7+'hO!CrQPO7+'hOOQO7+'i7+'iO$hQPO,59hO$hQPO<<G{O!CwQPO<<KSOOQO<<KS<<KSOOQO1G/S1G/SOOQOAN=gAN=gOOQOAN@nAN@n",
|
|
1354
|
+
stateData: "!DT~O$}OS%OOS~OTPO!hQO!ySO#QUO#TVO#YXO#]YO#f[O$paO~OShO%QkO~OSoOYqO[rO^sO!XuO!Z}O![}O!^xO#_!WO#m|O#r!OO$P!QO$Q!WO$T!SO$V!TO$[!XO$_![O$c!]O$h!aO%QvO~O!{wO~P!PO#V!gO~O#_!jO~O!hQO!ySO#QUO#TVO#YXO#]YO#f[O~O${!eX%]!eX%W!eX~P#rOShO~O%]!nOT$qX!h$qX!y$qX#Q$qX#T$qX#Y$qX#]$qX#f$qX$p$qX${$qX~O%]!nO~OSoOYqO[rO^sO!XuO!Z}O![}O#_!WO#m|O#r!OO$P!QO$Q!WO$T!SO$V!TO$[!XO$_![O$c!]O$h!aO%QvO~O%P!rOSUXfUXlUX!hUX!nUX!pUX!rUX!tUX!vUX!yUX#QUX#TUX#YUX#]UX#fUX${UX%]UX%WUXqUXYUX[UX^UX!XUX!ZUX![UX#_UX#mUX#rUX$PUX$QUX$TUX$VUX$[UX$_UX$cUX$hUX%UUX~O%QUXoUX~P&tOS!sO~OS!vOl!uOf!iX!h!iX!n!iX!p!iX!r!iX!t!iX!v!iX!y!iX#Q!iX#T!iX#Y!iX#]!iX#f!iX${!iX%]!iX%W!iXo!iX~OS!vOl!uOf!jX!h!jX!n!jX!p!jX!r!jX!t!jX!v!jX!y!jX#Q!jX#T!jX#Y!jX#]!jX#f!jX${!jX%]!jX%W!jXo!jX~Of!|O!n!}O!p#OO!r#PO!t#QO!v#RO~O!h!fa!y!fa#Q!fa#T!fa#Y!fa#]!fa#f!fa${!fa%]!fa%W!fa~P,XO%Q#WOtUXxUX|UX!OUX!PUX!QUX!RUX!SUX!TUX!VUX!^UX!_UX!`UX!cUX#kUX#uUX#wUX#|UX#zUX~P&tOS!sO!^#XO~Ol!uOq#^Ot#ZOx#YO|#[O!O#^O!P#^O!Q#^O!R#^O!S#^O!T#^O!V#]O!XuO!Z#`O![#`O!^#aO!_#aO!`#aO!c#bO#k#dO~OS!vO!h!|X!y!|X#Q!|X#T!|X#Y!|X#]!|X#f!|X${!|X%U!|X%]!|X%W!|X~P.{O!hQO!ySO#QUO#TVO#YXO#]YO#f[O~P%gO%U#nO!h!wa!y!wa#Q!wa#T!wa#Y!wa#]!wa#f!wa${!wa%]!wa%W!wa~O#u#rO~P%gO%Q#vO~O%Q#wO~O#_#yO$Q#xO~O$Q#zO~O$Q#{O~O%Q#}O~O%Q$OO~OS$QO#_$QO~O#h$SO!h#da!y#da#Q#da#T#da#Y#da#]#da#f#da${#da%]#da%W#da~Ol!uO%Q$UO~O%Q$WO~O!h#Oa!y#Oa#Q#Oa#T#Oa#Y#Oa#]#Oa#f#Oa${#Oa%]#Oa%W#Oa~P/OO!h#Wa!y#Wa#Q#Wa#T#Wa#Y#Wa#]#Wa#f#Wa${#Wa%]#Wa%W#Wa~P/OO%P!rOSUafUalUa!hUa!nUa!pUa!rUa!tUa!vUa!yUa#QUa#TUa#YUa#]Ua#fUa${Ua%]UaqUatUaxUa|Ua!OUa!PUa!QUa!RUa!SUa!TUa!VUa!XUa!ZUa![Ua!^Ua!_Ua!`Ua!cUa#kUa%UUa%QUa%WUa#uUaoUa#wUa#|Ua#zUaYUa[Ua^Ua#_Ua#mUa#rUa$PUa$QUa$TUa$VUa$[Ua$_Ua$cUa$hUa~OS!vO~O%W$ZO~Of!|O~O!h!fi!y!fi#Q!fi#T!fi#Y!fi#]!fi#f!fi${!fi%]!fi%W!fi~P,XO%W$aO~P%gOS$bOYqO[rO^sO~O!V#]O!c#bO~O%Q$fO~O!XuO#m|O~O%W$oO~P/OO!h!wi!y!wi#Q!wi#T!wi#Y!wi#]!wi#f!wi${!wi%]!wi%W!wi~P!PO%U$qO!h!wi!y!wi#Q!wi#T!wi#Y!wi#]!wi#f!wi${!wi%]!wi%W!wi~O#u#rO~P/OO#u#rO#z$vO#|$wO~O!^%PO!{wO%W%OO~P%gOS%RO~Ot#ZOS#nal#naq#nax#na|#na!O#na!P#na!Q#na!R#na!S#na!T#na!V#na!X#na!Z#na![#na!^#na!_#na!`#na!c#na!h#na!y#na#Q#na#T#na#Y#na#]#na#f#na#k#na${#na%U#na%]#na%W#na#u#na#w#na#|#naf#na!n#na!p#na!r#na!t#na!v#na#z#naY#na[#na^#na#_#na#m#na#r#na$P#na$Q#na$T#na$V#na$[#na$_#na$c#na$h#na~OS%TO$Q%TO~O%U%WO!h#Ri!y#Ri#Q#Ri#T#Ri#Y#Ri#]#Ri#f#Ri${#Ri%]#Ri%W#Ri~O#a%YO#c%ZO!h#^X!y#^X#Q#^X#T#^X#Y#^X#]#^X#f#^X${#^X%U#^X%]#^X%W#^X~O%U%]O!h#Zi!y#Zi#Q#Zi#T#Zi#Y#Zi#]#Zi#f#Zi${#Zi%]#Zi%W#Zi~O#_%_O~OS%`OYqO[rO^sOf!|O!XuO!Z}O![}O#_!WO#m|O#r!OO$P!QO$Q!WO$T!SO$V!TO$[!XO$_![O$c!]O$h!aO~O%Q%mO~OS%nOYqO[rO^sOf!|O!XuO!Z}O![}O#_!WO#m|O#r!OO$P!QO$Q!WO$T!SO$V!TO$[!XO$_![O$c!]O$h!aO~O%P!rO~Oo%rOf!la!h!la!n!la!p!la!r!la!t!la!v!la!y!la#Q!la#T!la#Y!la#]!la#f!la${!la%]!la%W!la~O%U%vO%W%wO~P/OO%Q%xO~Oq#^Ot#ZO!O#^O!P#^O!Q#^O!R#^O!S#^O!T#^O!V#]O!XuO!Z#`O![#`O!^#aO!_#aO!`#aO!c#bO#k#dOSzilzixzi!hzi!yzi#Qzi#Tzi#Yzi#]zi#fzi${zi%Uzi%]zi%Wzi#uzi#wzi#|zifzi!nzi!pzi!rzi!tzi!vzi#zziYzi[zi^zi#_zi#mzi#rzi$Pzi$Qzi$Tzi$Vzi$[zi$_zi$czi$hzi~O|#[O~PISO|zi~PISOt#ZO!^#aO!_#aO!`#aOSzilziqzixzi|zi!Ozi!Pzi!Qzi!Rzi!Szi!Tzi!Vzi!Xzi!czi!hzi!yzi#Qzi#Tzi#Yzi#]zi#fzi#kzi${zi%Uzi%]zi%Wzi#uzi#wzi#|zifzi!nzi!pzi!rzi!tzi!vzi#zziYzi[zi^zi#_zi#mzi#rzi$Pzi$Qzi$Tzi$Vzi$[zi$_zi$czi$hzi~O!Z#`O![#`O~PMPO!Zzi![zi~PMPOt#ZOSzilziqzixzi|zi!Ozi!Pzi!Qzi!Rzi!Szi!Tzi!Vzi!Xzi!Zzi![zi!^zi!_zi!`zi!czi!hzi!yzi#Qzi#Tzi#Yzi#]zi#fzi#kzi${zi%Uzi%]zi%Wzi#uzi#wzi#|zifzi!nzi!pzi!rzi!tzi!vzi#zziYzi[zi^zi#_zi#mzi#rzi$Pzi$Qzi$Tzi$Vzi$[zi$_zi$czi$hzi~O!h!wq!y!wq#Q!wq#T!wq#Y!wq#]!wq#f!wq${!wq%]!wq%W!wq~P!PO%U%}O!h!wq!y!wq#Q!wq#T!wq#Y!wq#]!wq#f!wq${!wq%]!wq%W!wq~O#w&RO~P/OO%W&TO~O%W&UO~P/OO%W&UO~O!hQO~O!h#Rq!y#Rq#Q#Rq#T#Rq#Y#Rq#]#Rq#f#Rq${#Rq%]#Rq%W#Rq~P!PO%U&YO!h#Rq!y#Rq#Q#Rq#T#Rq#Y#Rq#]#Rq#f#Rq${#Rq%]#Rq%W#Rq~O!h#Zq!y#Zq#Q#Zq#T#Zq#Y#Zq#]#Zq#f#Zq${#Zq%]#Zq%W#Zq~OS$QO#_$QO~P!*`O%U&[O~P!*`O%P!rO%Q#WOlUXqUXtUXxUX|UX!OUX!PUX!QUX!RUX!SUX!TUX!VUX!XUX!ZUX![UX!^UX!_UX!`UX!cUX#kUX$lmX~OSWXYWX[WX^WX~P!+cO$Q#zOSWXYWX[WX^WX~O$Q#{OSWXYWX[WX^WX~O#_#yO$Q#xOSWXYWX[WX^WX~OS&^OYqO[rO^sO~Oh&`Oj&aO~Oq#^Ox#YO|#[O!O#^O!P#^O!Q#^O!R#^O!S#^O!T#^O!V#]O!XuO!Z#`O![#`O!^#aO!_#aO!`#aO!c#bO#k#dO~Ol!uOt&dO~P!.|O%U&nOS$sXY$sX[$sX^$sXf$sX!X$sX!Z$sX![$sX#_$sX#m$sX#r$sX$P$sX$Q$sX$T$sX$V$sX$[$sX$_$sX$c$sX$h$sX%W$sX~O%W&pO~PDvO$l&qO~O%U&sOS$zXY$zX[$zX^$zXf$zX!X$zX!Z$zX![$zX#_$zX#m$zX#r$zX$P$zX$Q$zX$T$zX$V$zX$[$zX$_$zX$c$zX$h$zX%W$zX~O%W&uO~PFYOo%rOf!li!h!li!n!li!p!li!r!li!t!li!v!li!y!li#Q!li#T!li#Y!li#]!li#f!li${!li%]!li%W!li~O%U&yO%W&zO~O%W&zO~P%gO%U'OO%W!dX~P/OO%W'PO~O!h!wy!y!wy#Q!wy#T!wy#Y!wy#]!wy#f!wy${!wy%]!wy%W!wy~P!PO#|#xa~P/OO%W'SO~P/OO!h#Ry!y#Ry#Q#Ry#T#Ry#Y#Ry#]#Ry#f#Ry${#Ry%]#Ry%W#Ry~P!POS$QO#_$QO!h#Zy!y#Zy#Q#Zy#T#Zy#Y#Zy#]#Zy#f#Zy${#Zy%]#Zy%W#Zy~Ob'WOSVaYVa[Va^VafVa!XVa!ZVa![Va#_Va#mVa#rVa$PVa$QVa$TVa$VVa$[Va$_Va$cVa$hVa%UVa%WVa~Ol!uOo%rO~O%Q'_O~O%W'iO~Of!lq!h!lq!n!lq!p!lq!r!lq!t!lq!v!lq!y!lq#Q!lq#T!lq#Y!lq#]!lq#f!lq${!lq%]!lq%W!lq~P/OO%W'lO~P%gO%U$ta%W$ta~P/OO%W'mO~O%U'nO%W!da~O%W!da~P%gO#u#sq#z#sq#|#sq~P/OO%W'oO~P/OO%W'pO~O%Q'tO~Oq#^Ot#ZO!O#^O!P#^O!Q#^O!R#^O!S#^O!T#^O!V#]O!XuO!Z#`O![#`O!^#aO!_#aO!`#aO!c#bO#k#dOlvixvi~O|#[O~P!<gO|vi~P!<gOt#ZO!^#aO!_#aO!`#aOlviqvixvi|vi!Ovi!Pvi!Qvi!Rvi!Svi!Tvi!Vvi!Xvi!cvi#kvi~O!Z#`O![#`O~P!>SO!Zvi![vi~P!>SOt#ZOlviqvixvi|vi!Ovi!Pvi!Qvi!Rvi!Svi!Tvi!Vvi!Xvi!Zvi![vi!^vi!_vi!`vi!cvi#kvi~OSriYri[ri^rifri#_ri#mri#rri$Pri$Qri$Tri$Vri$[ri$_ri$cri$hri%Uri%Wri~P/OOf!ly!h!ly!n!ly!p!ly!r!ly!t!ly!v!ly!y!ly#Q!ly#T!ly#Y!ly#]!ly#f!ly${!ly%]!ly%W!ly~P/OO%W!di~P%gOq'wO~O%W'zO~O%W'}O~O%O![t$l!^!_~",
|
|
1355
|
+
goto: "! b%_PP%`%dPP%h'R'V'ZP(iP)wP+V+Y+]P+`+h+nP+{P+{P,OP,e-TP-aP+`-gP-m-g-vP._._/_P/xPPPPPP0eP1SP2yPP3hPPP._4XP4z5W5r6PP6a6a6f7k7oP7oP7oP7oP7oP5r7sP8QP8W8i5r8tP5r9RP9`P5r9fP5r9sP:QP:YP:YP5r:]P:jP._:mP;YP<j=n<j>rP?v?|P@SP@V@]P@aP<j@kPPAoBsPBsPAoCwCwD{P<jFPPGT<jGWP<jH[<j<jP6k-g-gP%`%`H_PHcHiI|JSJ^JmJsKRKXKcPPPPPPKiKmKsPM}PNW<jCw._P! ^TcOdT`OdUjR#S$^#S!ZTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tQ!l`Q!mbQ&c%fS'q'Z'xR'{'wT%i$U%kT%d$U%k#O!_Tfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$W$f$q$z%Q%W%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tU$b#Z&X&dS%a$U%kR&^%d#O!`Tfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$W$f$q$z%Q%W%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tU$b#Z&X&dS%b$U%kR&^%d#O!^Tfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$W$f$q$z%Q%W%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tU$b#Z&X&dS%c$U%kR&^%dR&_%dR'Y&_R'X&_S%i$U%kT%o$W%qX%f$U$W%k%qS#Sn#VQ$^#TX%e$U$W%k%qR&b%eQ!xjQ!{lQ#ltQ$V!lQ&X%VQ&m%gR'[&cQ!wjQ!zlQ#ktQ$Y!xQ$[!{Q$n#lW%l$U$W%k%qQ'g&mR's'[Q%s$]Q&w%tQ'Z&cR'x'sQ'r'ZR'|'xX%h$U$W%k%qQ$c#ZQ'U&XR']&dt#ft!p!q#m#q$`${$}%V%y&Q&V&v&{'R'T'h'jR&h%g!{!cTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$f$q$z%Q%W%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tx#gt!p!q#m#q$`$i${$}%V%y&Q&V&v&{'R'T'b'h'jR&i%g|#ht!p!q#m#q$`$i$j${$}%V%y&Q&V&v&{'R'T'b'c'h'jR&j%g!O#^t!p!q#m#q$`$i$j${$}%V%g%y&Q&V&v&{'R'T'b'c'h'jT$d#_&e#S}Tfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't|#_t!p!q#m#q$`$i$j${$}%V%y&Q&V&v&{'R'T'b'c'h'jQ$h#eQ&e%gR'a&g!Q#it!p!q#m#q$`$i$j$k${$}%V%y&Q&V&v&{'R'T'b'c'd'h'jR&k%g!U#jt!p!q#m#q$`$i$j$k$l${$}%V%y&Q&V&v&{'R'T'b'c'd'e'h'jR&l%g|#ct!p!q#m#q$`$i$j${$}%V%y&Q&V&v&{'R'T'b'c'h'jQ$e#_Q&f%gR'^&eQ%z$fQ&|%xQ'u'_R'y'tSeOdS!ykvQ$|#vQ%z$fQ&r%mQ&|%xQ'u'_R'y'tg^O_dkv#v$f%m%x'_'tfRO_dkv#v$f%m%x'_'tR&W%UVmR#S$^UlR#S$^!{!bTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$f$q$z%Q%W%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tT#Un#VT#Tn#VgTO_dkv#v$f%m%x'_'tQ{TR%Q#wQzTQ#p{Q$P!h]$p#n$q%W%|%}&YcyT{!h#n$q%W%|%}&YgfO_dkv#v$f%m%x'_'tgWO_dkv#v$f%m%x'_'tQ!hWR!iZggO_dkv#v$f%m%x'_'tgZO_dkv#v$f%m%x'_'tQ$R!iV&Z%]&['VR%[$Qg]O_dkv#v$f%m%x'_'tR$T!j|#et!p!q#m#q$`$i$j${$}%V%y&Q&V&v&{'R'T'b'c'h'jR&g%g#S!VTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tQ$g#eQ%{$hQ'`&gR'v'a#T!aTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!dTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!PTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tX#s!P#q#t$tX#u!P#q#t$tR&S${Q$y#tR&P$tT$z#t$tQ$x#tS&O$t$yR'Q&P#T!RTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!WTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!UTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!ZTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!YTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n't#T!eTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tR%U#}#T!fTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$U$W$f$q$z%Q%W%k%q%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tR%S#yTbOdQdOR!od#SiR`bfgv!P!d#S#W#f#g#h#i#j#u#w$O$U$W$^$f$z%Q%f%k%q%s%v%x&S&W&h&i&j&k&l&q&w&y'O'Z'_'k'n't'w'xbpT{!h#n$q%W%|%}&YT!tipQ%k$UR&o%kQ%u$`S&x%u&}R&}%yd_Odkv#v$f%m%x'_'tR!k_Q#VnR$_#VQ#ozU$r#o$s%XQ$s#pR%X$PQ%^$RR&]%^Q#t!PQ$t#qT$u#t$tQ%q$WR&t%qT%j$U%kX%g$U$W%k%qbtT{!h#n$q%W%|%}&YQ!pfQ!qgQ#mvQ#q!PQ#|!dQ$`#WQ$i#fQ$j#gQ$k#hQ$l#iQ$m#jQ${#uQ$}#wQ%V$OW%y$f%x'_'tQ&Q$zQ&V%QQ&v%sY&{%v&y'O'k'nQ'R&SQ'T&WQ'b&hQ'c&iQ'd&jQ'e&kQ'f&lQ'h&qR'j&wQnRQ$]#SR%t$^!z!cTfgv{!P!d!h#W#f#g#h#i#j#n#u#w$O$f$q$z%Q%W%s%v%x%|%}&S&W&Y&h&i&j&k&l&q&w&y'O'_'k'n'tX%h$U$W%k%qT%p$W%q",
|
|
1356
|
+
nodeNames: "\u26A0 Program TableStatement Kw Identifier table Ref ColumnDef ColumnName Kw date Kw timestamp Kw interval DataType PrimaryKey Kw primary_key JoinDef JoinType Kw join Kw one Kw many Kw as Alias Kw on BinaryExpression = ComputedDef TypeCastExpression :: CastType BinaryExpression Kw or TypeCastExpression BinaryExpression Kw and ComparisonOp != <> < > <= >= Kw like Kw not AddOp + - MulOp * / % InExpression Kw in InValueList QueryStatement FromClause Kw from TableName Subquery SubqueryExpression JoinClause Kw inner Kw left Kw right Kw full Kw cross SelectClause Kw select Kw distinct SelectItem Wildcard WhereClause Kw where GroupByClause Kw group Kw by HavingClause Kw having OrderByClause Kw order OrderItem Number Kw asc Kw desc LimitClause Kw limit Kw offset NullTestExpression Kw is Kw null UnaryExpression UnaryOperator CaseExpression Kw case WhenClause Kw when Kw then ElseClause Kw else Kw end ExistsExpression Kw exists String Boolean Kw true Kw false Null FunctionCall Count Kw count ExtractExpression Kw extract ExtractUnit CastExpression Kw cast IntervalExpression IntervalUnit DateExpression TimestampExpression Param Parenthetical InExpression NullTestExpression : ViewStatement ExtendStatement Kw extend",
|
|
1357
|
+
maxTerm: 198,
|
|
1348
1358
|
nodeProps: [
|
|
1349
|
-
["group", -16, 6,
|
|
1359
|
+
["group", -16, 6, 107, 122, 124, 137, 140, 141, 146, 147, 148, 151, 155, 158, 160, 161, 162, "Expression Expression", -11, 32, 35, 38, 41, 42, 63, 73, 117, 163, 164, 165, "Expression", -2, 71, 72, "TablePrimary"]
|
|
1350
1360
|
],
|
|
1351
1361
|
skippedNodes: [0],
|
|
1352
1362
|
repeatNodeCount: 10,
|
|
1353
|
-
tokenData: "*w~RoX^#Spq#Sqr#wrs$Stu$quv%cwx%hxy&Qyz&Vz{&[{|&a|}&f}!O&k!O!P'[!P!Q'a!Q![(p![!])Z!]!^)h!^!_)m!_!`*S!`!a*X!c!}*f#T#o*f#y#z#S$f$g#S#BY#BZ#S$IS$I_#S$I|$JO#S$JT$JU#S$KV$KW#S&FU&FV#S~#XY
|
|
1363
|
+
tokenData: "*w~RoX^#Spq#Sqr#wrs$Stu$quv%cwx%hxy&Qyz&Vz{&[{|&a|}&f}!O&k!O!P'[!P!Q'a!Q![(p![!])Z!]!^)h!^!_)m!_!`*S!`!a*X!c!}*f#T#o*f#y#z#S$f$g#S#BY#BZ#S$IS$I_#S$I|$JO#S$JT$JU#S$KV$KW#S&FU&FV#S~#XY$}~X^#Spq#S#y#z#S$f$g#S#BY#BZ#S$IS$I_#S$I|$JO#S$JT$JU#S$KV$KW#S&FU&FV#S~#zP!_!`#}~$SO!O~~$VTOr$Srs$fs;'S$S;'S;=`$k<%lO$S~$kO$Q~~$nP;=`<%l$S~$tS!Q![%Q!c!}%Q#R#S%Q#T#o%Q~%VS$h~!Q![%Q!c!}%Q#R#S%Q#T#o%Q~%hO!`~~%kTOw%hwx$fx;'S%h;'S;=`%z<%lO%h~%}P;=`<%l%h~&VO%Q~~&[O%W~~&aO!^~~&fO!Z~~&kO%U~~&pP![~}!O&s~&xS%O~OY&sZ;'S&s;'S;=`'U<%lO&s~'XP;=`<%l&s~'aO%P~~'fP!_~z{'i~'lTOz'iz{'{{;'S'i;'S;=`(j<%lO'i~(OVOz'iz{'{{!P'i!P!Q(e!Q;'S'i;'S;=`(j<%lO'i~(jO%O~~(mP;=`<%l'i~(uQ#_~!O!P({!Q![(p~)OP!Q![)R~)WP#_~!Q![)R~)`P$l~![!])c~)hOt~~)mO%]~~)rQ!Q~!_!`)x!`!a)}~)}O!S~~*SO!P~~*XOq~~*^P!R~!_!`*a~*fO!T~~*kSS~!Q![*f!c!}*f#R#S*f#T#o*f",
|
|
1354
1364
|
tokenizers: [0],
|
|
1355
1365
|
topRules: { "Program": [0, 1] },
|
|
1356
1366
|
specialized: [{ term: 4, get: (value, stack) => specializeIdentifier(value, stack) << 1, external: specializeIdentifier }, { term: 4, get: (value) => spec_Identifier[value] || -1 }],
|
|
1357
|
-
tokenPrec:
|
|
1367
|
+
tokenPrec: 3724
|
|
1358
1368
|
});
|
|
1359
1369
|
}
|
|
1360
1370
|
});
|
package/dist/docs/graphene.md
CHANGED
|
@@ -22,9 +22,6 @@ Graphene also has a CLI that lets you check syntax, run queries, serve data apps
|
|
|
22
22
|
- [Using scalar stored expressions (dimensions) in queries](#using-scalar-stored-expressions-dimensions-in-queries)
|
|
23
23
|
- [Using aggregative stored expressions (measures) in queries](#using-aggregative-stored-expressions-measures-in-queries)
|
|
24
24
|
- [Safe aggregation in fan-outs](#safe-aggregation-in-fan-outs)
|
|
25
|
-
- [Working with dates, timestamps, and intervals](#working-with-dates-timestamps-and-intervals)
|
|
26
|
-
- [Date and timestamp literals](#date-and-timestamp-literals)
|
|
27
|
-
- [Interval literals](#interval-literals)
|
|
28
25
|
- [Available functions](#available-functions)
|
|
29
26
|
- [Aggregate functions](#aggregate-functions)
|
|
30
27
|
- [Date and time functions](#date-and-time-functions)
|
|
@@ -578,6 +575,7 @@ from sales_per_store
|
|
|
578
575
|
- Expressions in `group by` are implicitly selected, so `from orders select avg(amount) group by user_id` will return two columns.
|
|
579
576
|
- `count` is a reserved word. Do not alias your columns as `count`.
|
|
580
577
|
- Window functions and set operations (`union [all]`, `intersect`, `except`) are not supported.
|
|
578
|
+
- Date and timestamp literals can be written with explicit keywords (`date '2024-01-01'` or `timestamp '2024-01-01 12:00:00'`), but these keywords are optional when the expected type is known from context (e.g., when comparing against a date or timestamp column). Interval literals always require the `interval` keyword.
|
|
581
579
|
|
|
582
580
|
## `table as` statements
|
|
583
581
|
|
|
@@ -345,19 +345,21 @@
|
|
|
345
345
|
|
|
346
346
|
{#if groupBy}
|
|
347
347
|
{#each sortedGroupNames as groupName (groupName)}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
348
|
+
{#if groupType !== 'section'}
|
|
349
|
+
<TableGroupRow
|
|
350
|
+
{groupName}
|
|
351
|
+
currentGroupData={groupedData[groupName]}
|
|
352
|
+
toggled={groupToggleStates[groupName]}
|
|
353
|
+
{columnSummary}
|
|
354
|
+
{rowNumbers}
|
|
355
|
+
rowColor={$accordionRowColorStore}
|
|
356
|
+
{subtotals}
|
|
357
|
+
on:toggle={handleToggle}
|
|
358
|
+
{orderedColumns}
|
|
359
|
+
{compact}
|
|
360
|
+
/>
|
|
361
|
+
{/if}
|
|
362
|
+
{#if groupType === 'section' || groupToggleStates[groupName]}
|
|
361
363
|
<TableRow
|
|
362
364
|
displayedData={groupedData[groupName]}
|
|
363
365
|
{rowShading}
|
|
@@ -372,6 +374,7 @@
|
|
|
372
374
|
groupNamePosition={groupNamePosition}
|
|
373
375
|
orderedColumns={orderedColumns}
|
|
374
376
|
index={groupOffsets[groupName] ?? 0}
|
|
377
|
+
rowSpan={groupedData[groupName].length}
|
|
375
378
|
/>
|
|
376
379
|
{#if subtotals}
|
|
377
380
|
<TableSubtotalRow
|
package/package.json
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphenedata/cli",
|
|
3
|
-
"main": "
|
|
3
|
+
"main": "bin.js",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "Graphene Systems Inc",
|
|
6
|
-
"version": "0.0.
|
|
6
|
+
"version": "0.0.13",
|
|
7
7
|
"license": "Elastic-2.0",
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=16"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
|
+
"bin.js",
|
|
13
14
|
"package.json",
|
|
14
15
|
"LICENSE.md",
|
|
15
16
|
"THIRD_PARTY_NOTICES.md"
|
|
16
17
|
],
|
|
17
18
|
"bin": {
|
|
18
|
-
"graphene": "./
|
|
19
|
+
"graphene": "./bin.js"
|
|
19
20
|
},
|
|
20
21
|
"exports": {
|
|
21
22
|
"./ui": {
|
package/cli.ts
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import {Command} from 'commander'
|
|
4
|
-
import {printDiagnostics, printTable} from './printer.ts'
|
|
5
|
-
import {analyze, getDiagnostics, loadWorkspace, toSql, type Query} from '../lang/core.ts'
|
|
6
|
-
import fs from 'fs-extra'
|
|
7
|
-
import path from 'path'
|
|
8
|
-
import {fileURLToPath} from 'url'
|
|
9
|
-
import dotenv from 'dotenv'
|
|
10
|
-
import {config, loadConfig} from '../lang/config.ts'
|
|
11
|
-
import {runServeInBackground, stopGrapheneIfRunning} from './background.ts'
|
|
12
|
-
import {check} from './check.ts'
|
|
13
|
-
import {getConnection, runQuery} from './connections/index.ts'
|
|
14
|
-
import {loginPkce} from './auth.ts'
|
|
15
|
-
|
|
16
|
-
dotenv.config({quiet: true})
|
|
17
|
-
const program = new Command()
|
|
18
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
19
|
-
// in dev: cli/cli.ts -> cli/package.json. in dist: cli/dist/cli/cli.js -> cli/package.json
|
|
20
|
-
const pkgPath = fs.existsSync(path.join(__dirname, 'package.json')) ? path.join(__dirname, 'package.json') : path.join(__dirname, '../../package.json')
|
|
21
|
-
const pkg = fs.readJsonSync(pkgPath)
|
|
22
|
-
|
|
23
|
-
program.name('graphene').description('Graphene CLI').version(pkg.version, '-v, --version')
|
|
24
|
-
|
|
25
|
-
program.hook('preAction', async () => {
|
|
26
|
-
if (process.env.CLI_DELAY) { // useful if you want to attach a debugger
|
|
27
|
-
await new Promise(r => setTimeout(r, 1000))
|
|
28
|
-
}
|
|
29
|
-
loadConfig(process.cwd())
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
program.command('compile')
|
|
33
|
-
.description('Translate a query to SQL and print it')
|
|
34
|
-
.argument('[input]', 'Path to file, a raw string, or "-" for stdin')
|
|
35
|
-
.action(async (input: string | undefined) => {
|
|
36
|
-
await loadWorkspace(process.cwd(), false)
|
|
37
|
-
let sql = await readInput(input)
|
|
38
|
-
let queries = analyze(sql)
|
|
39
|
-
if (!validQuery(queries)) return
|
|
40
|
-
console.log(toSql(queries[0]))
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
program.command('run')
|
|
44
|
-
.description('Run a query against your database')
|
|
45
|
-
.argument('[input]', 'Path to file, a raw string, or "-" for stdin')
|
|
46
|
-
.action(async (input: string | undefined) => {
|
|
47
|
-
await loadWorkspace(process.cwd(), false)
|
|
48
|
-
let gsql = await readInput(input)
|
|
49
|
-
let queries = analyze(gsql)
|
|
50
|
-
if (!validQuery(queries)) return
|
|
51
|
-
let sql = toSql(queries[0])
|
|
52
|
-
let res = await runQuery(sql)
|
|
53
|
-
printTable(res.rows)
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
program.command('schema')
|
|
57
|
-
.description('Inspect database tables or describe a table')
|
|
58
|
-
.argument('[schema | table]', 'Optional schema or table name to describe')
|
|
59
|
-
.action(async (tableArg: string) => {
|
|
60
|
-
let connection = await getConnection()
|
|
61
|
-
let datasets = await connection.listDatasets()
|
|
62
|
-
|
|
63
|
-
// if there's no arg and more than one dataset, just list the datasets
|
|
64
|
-
if (!tableArg && datasets.length > 1) {
|
|
65
|
-
return console.log(`Datasets available:\n${datasets.join('\n')}`)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// figure out if you're wanting to list tables in a schema/dataset
|
|
69
|
-
let dsToList: string | null = null
|
|
70
|
-
let parts = tableArg ? tableArg.split('.') : []
|
|
71
|
-
if (datasets.includes(tableArg)) dsToList = tableArg // you gave the name of a dataset
|
|
72
|
-
else if (!tableArg && datasets.length == 1) dsToList = datasets[0] // only one dataset, and no args
|
|
73
|
-
else if (!tableArg && config.namespace) dsToList = config.namespace // default namespace configured
|
|
74
|
-
else if (!tableArg && config.dialect == 'duckdb') dsToList = '<default>'
|
|
75
|
-
else if (tableArg && config.dialect == 'snowflake' && parts.length == 2) dsToList = tableArg
|
|
76
|
-
|
|
77
|
-
if (dsToList) {
|
|
78
|
-
let tables = await connection.listTables(dsToList)
|
|
79
|
-
return console.log(`Tables${dsToList ? ` in ${dsToList}` : ''}:\n${tables.join('\n')}`)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// otherwise, assume you're wanting to see tables
|
|
83
|
-
let cols = await connection.describeTable(tableArg)
|
|
84
|
-
if (!cols.length) return console.log(`Table ${tableArg} not found`)
|
|
85
|
-
console.log(`table ${tableArg} (`)
|
|
86
|
-
cols.forEach(col => console.log(` ${col.name} ${col.dataType}`))
|
|
87
|
-
console.log(')')
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
program.command('serve')
|
|
91
|
-
.description('Run the local server')
|
|
92
|
-
.option('--bg', 'Run the server in the background')
|
|
93
|
-
.action(async (options: {bg?: boolean}) => {
|
|
94
|
-
await stopGrapheneIfRunning()
|
|
95
|
-
if (options.bg) {
|
|
96
|
-
await runServeInBackground()
|
|
97
|
-
process.exit(0)
|
|
98
|
-
} else {
|
|
99
|
-
let mod = await import('./serve2.ts') // load dynamically, so we're not pulling in a bunch of deps we might not need
|
|
100
|
-
await mod.serve2()
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
program.command('stop')
|
|
105
|
-
.description('Stop the local server')
|
|
106
|
-
.action(async () => { await stopGrapheneIfRunning() })
|
|
107
|
-
|
|
108
|
-
program.command('check')
|
|
109
|
-
.description('Check the project for errors, optionally capturing a page screenshot')
|
|
110
|
-
.argument('[mdFile]', 'Markdown file to check (e.g., index.md)')
|
|
111
|
-
.option('-c, --chart <chartTitle>', 'Title of a specific chart to capture')
|
|
112
|
-
.action(async (mdArg: string | undefined, options: {chart?: string}) => {
|
|
113
|
-
let res = await check({mdArg, chart: options.chart})
|
|
114
|
-
process.exit(res ? 0 : 1) // import to call `exit`, bc if we started the server in the background, just returning won't actually exit the process.
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
program.command('login')
|
|
118
|
-
.description('Log in to Graphene Cloud')
|
|
119
|
-
.action(async () => {
|
|
120
|
-
await loginPkce()
|
|
121
|
-
console.log('Successfully logged in')
|
|
122
|
-
process.exit(0)
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
program.parse(process.argv)
|
|
126
|
-
|
|
127
|
-
async function readInput (arg): Promise<string> {
|
|
128
|
-
if (!arg || arg === '-') {
|
|
129
|
-
return await new Promise<string>((resolve) => {
|
|
130
|
-
let data = ''
|
|
131
|
-
process.stdin.setEncoding('utf-8')
|
|
132
|
-
process.stdin.on('data', (chunk) => (data += chunk))
|
|
133
|
-
process.stdin.on('end', () => resolve(data))
|
|
134
|
-
process.stdin.resume()
|
|
135
|
-
})
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
let absolutePath = path.resolve(arg)
|
|
139
|
-
if (fs.existsSync(absolutePath)) {
|
|
140
|
-
return await fs.promises.readFile(absolutePath, 'utf-8')
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return arg
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function validQuery (queries: Query[]): boolean {
|
|
147
|
-
if (getDiagnostics().length) {
|
|
148
|
-
printDiagnostics(getDiagnostics())
|
|
149
|
-
process.exit(1)
|
|
150
|
-
}
|
|
151
|
-
if (queries.length == 0) {
|
|
152
|
-
console.warn('No queries found')
|
|
153
|
-
process.exit(1)
|
|
154
|
-
}
|
|
155
|
-
return true
|
|
156
|
-
}
|