diff --git a/cli/cli.test.ts b/cli/cli.test.ts
index 433829a5..cac7498a 100644
--- a/cli/cli.test.ts
+++ b/cli/cli.test.ts
@@ -214,27 +214,27 @@ describe('cli run', () => {
})
it('runs a named query from a markdown file', async () => {
- let res = await runCli(['run', 'index.md', '--query', 'performance_by_year'], {cwd: flightDir})
+ let res = await runCli(['run', 'pages/operations_overview.md', '--query', 'performance_by_year'], {cwd: flightDir})
expectCliSuccess(res, 'run markdown query')
expect(res.stdout.toLowerCase()).toContain('flight_count')
})
it('prints csv for a named query from a markdown file with --format csv', async () => {
- let res = await runCli(['run', 'index.md', '--query', 'performance_by_year', '--format', 'csv'], {cwd: flightDir})
+ let res = await runCli(['run', 'pages/operations_overview.md', '--query', 'performance_by_year', '--format', 'csv'], {cwd: flightDir})
expectCliSuccess(res, 'run markdown query as csv')
expect(res.stdout.startsWith('year,status,flight_count\n')).toBe(true)
expect(res.stdout).not.toContain('┌')
})
it('runs a parameterized named query from a markdown file with --input', async () => {
- let res = await runCli(['run', 'carrier_detail.md', '--query', 'carrier_info', '--input', 'carrier=AA'], {cwd: flightDir})
+ let res = await runCli(['run', 'pages/carrier_detail.md', '--query', 'carrier_info', '--input', 'carrier=AA'], {cwd: flightDir})
expectCliSuccess(res, 'run parameterized markdown query')
expect(res.stdout).toContain('AA')
})
it('runs a markdown page in headless mode', async () => {
try {
- let res = await runCli(['run', 'index.md', '--headless', '--chart', 'Flight Status by Year'], {cwd: flightDir, env: {NODE_ENV: 'development'}})
+ let res = await runCli(['run', 'pages/operations_overview.md', '--headless', '--chart', 'Flight Status by Year'], {cwd: flightDir, env: {NODE_ENV: 'development'}})
expectCliSuccess(res, 'run markdown page headless')
expect(res.stdout).toContain('No errors found')
expect(res.stdout).toContain('Screenshot saved to')
@@ -244,7 +244,7 @@ describe('cli run', () => {
})
it('prints a clean error for a missing markdown query input', async () => {
- let res = await runCli(['run', 'carrier_detail.md', '--query', 'carrier_info'], {cwd: flightDir})
+ let res = await runCli(['run', 'pages/carrier_detail.md', '--query', 'carrier_info'], {cwd: flightDir})
expect(res.code).toBe(1)
expect(res.stderr.trim()).toBe('Missing param $carrier')
})
diff --git a/cli/cli.ts b/cli/cli.ts
index 80c2987a..577b6959 100755
--- a/cli/cli.ts
+++ b/cli/cli.ts
@@ -160,8 +160,8 @@ program
let datasets = await connection.listDatasets()
let matchedDataset = tableArg ? findCaseInsensitive(datasets, tableArg) : null
- // if there's no arg and more than one dataset, just list the datasets
- if (!tableArg && datasets.length > 1) {
+ // If there's no configured namespace and more than one dataset, list the datasets.
+ if (!tableArg && !config.defaultNamespace && datasets.length > 1) {
return console.log(`Datasets available:\n${datasets.join('\n')}`)
}
diff --git a/cli/schema.test.ts b/cli/schema.test.ts
index 35d16f3c..1f1b36f4 100644
--- a/cli/schema.test.ts
+++ b/cli/schema.test.ts
@@ -180,7 +180,7 @@ describe.skipIf(!process.env.SLOW_TEST)('bigquery', () => {
let res = await runCli(['schema', tableName], ecommDir)
expectCliSuccess(res, 'schema describe table (bigquery)')
let output = res.stdout.toLowerCase()
- expect(output).toContain('tables in demo_dataset:')
+ expect(output).toContain(`table ${tableName.toLowerCase()} (`)
})
})
diff --git a/examples/flights/AGENTS.md b/examples/flights/AGENTS.md
index 615c1266..70158f88 100644
--- a/examples/flights/AGENTS.md
+++ b/examples/flights/AGENTS.md
@@ -1,20 +1,15 @@
-# RULES
+## About the data
-- Graphene contains languages and tools that you do not already know.
-- Before writing code in this directory, you MUST read `@../../docs/base.md` **in its entirety**.
-- You MUST also read relevant reference docs in `@../../docs/references/*.md` before implementing or editing related functionality.
-- Treat reference docs as required context, not optional reading.
-- If a task touches multiple areas (for example: GSQL + chart components), read all applicable reference files first.
-- If unsure which reference applies, start with `@../../docs/references/gsql.md`, then load additional references based on the components/functions used.
-- You will be docked for writing code here without completing the required documentation reading.
+- This is an example Graphene project to analyze FAA flight data from 2000-2005.
+- All available data is in `./tables`
-## Reference docs
+## Instructions
-- Core overview: `@../../docs/base.md`
-- CLI usage: `@../../docs/cli.md`
-- Best practices: `@../../docs/best-practices.md`
-- Detailed feature/component references: `@../../docs/references/*.md`
-
-# About this data
-
-This is a Graphene project covering FAA flight data from 2000 to 2005. You can find the Graphene tables in @./tables.
+- ALWAYS read the following before using the graphene CLI or editing .gsql or .md:
+ - Core overview: `@../../docs/base.md`
+ - CLI usage: `@../../docs/cli.md`
+ - Best practices: `@../../docs/best-practices.md`
+- Additional reference documentation is available in the `@../../docs/references` folder.
+- Assume all DuckDB functions are available when writing GSQL.
+- This example project uses pnpm, so run the Graphene CLI using `pnpm graphene ...`.
+- If you have an in-app browser tool, use it to show the user any changes you make to a Graphene page.
diff --git a/examples/flights/assets/preview_carrier_detail.png b/examples/flights/assets/preview_carrier_detail.png
new file mode 100644
index 00000000..ac2330e3
Binary files /dev/null and b/examples/flights/assets/preview_carrier_detail.png differ
diff --git a/examples/flights/assets/preview_delay_factors.png b/examples/flights/assets/preview_delay_factors.png
new file mode 100644
index 00000000..767a489a
Binary files /dev/null and b/examples/flights/assets/preview_delay_factors.png differ
diff --git a/examples/flights/assets/preview_operations_overview.png b/examples/flights/assets/preview_operations_overview.png
new file mode 100644
index 00000000..759ca579
Binary files /dev/null and b/examples/flights/assets/preview_operations_overview.png differ
diff --git a/examples/flights/control_room.md b/examples/flights/control_room.md
deleted file mode 100644
index a0660a46..00000000
--- a/examples/flights/control_room.md
+++ /dev/null
@@ -1,514 +0,0 @@
----
-title: Flight Control Room
-layout: dashboard
----
-
-
-
-```gsql ops_kpis
-from flights
-select
- count() as flights,
- on_time_departure_rate,
- cancellation_rate,
- round(avg(taxi_out), 1) as avg_taxi_out
-```
-
-```gsql peak_routes
-from flights
-where cancelled = 'N'
-select
- origin || ' -> ' || destination as route,
- count() as flights,
- on_time_arrival_rate
-order by flights desc
-limit 6
-```
-
-```gsql hourly_status
-from flights
-where extract(hour from dep_time)::integer between 5 and 23
-select
- extract(hour from dep_time)::integer as hour,
- status,
- count() as flights
-order by hour, status
-```
-
-```gsql tower_load
-from flights
-where cancelled = 'N'
-select
- origin as airport,
- origin_airport.city as city,
- count() as flights,
- avg(dep_delay) as avg_delay,
- on_time_departure_rate
-having count() > 3000
-order by flights desc
-limit 12
-```
-
-```gsql departure_banks
-from flights
-where cancelled = 'N'
-select
- case
- when extract(hour from dep_time)::integer < 10 then 'Morning'
- when extract(hour from dep_time)::integer < 14 then 'Midday'
- when extract(hour from dep_time)::integer < 18 then 'Afternoon'
- else 'Evening'
- end as bank,
- case
- when extract(hour from dep_time)::integer < 10 then 1
- when extract(hour from dep_time)::integer < 14 then 2
- when extract(hour from dep_time)::integer < 18 then 3
- else 4
- end as sort_key,
- count() as flights,
- round(avg(dep_delay), 1) as avg_delay,
- on_time_departure_rate
-order by sort_key
-```
-
-
-
-
-
FAA operations log • 2000-2005
-
Custom markup turns a dashboard into a control room.
-
This page is regular Graphene markdown, but the layout is hand-built with HTML and CSS. Components are embedded inside custom panels, metric strips, and route boards without leaving the dashboard file.
-
-
-
-
-
-
-
Flights tracked
-
-
All scheduled rows in the local FAA sample
-
-
-
On-time departures
-
-
Actual departure at or before schedule
-
-
-
Cancellation rate
-
-
Flights cancelled before departure
-
-
-
Avg taxi-out
-
-
Minutes from gate pushback to takeoff
-
-
-
-
-
-
-
Hourly departure board
- Status mix by scheduled hour
-
-
-
-
-
-
-
-
-
-
-
-
-
-
min
-
on-time departures
-
-
-
-
min
-
on-time departures
-
-
-
-
min
-
on-time departures
-
-
-
-
min
-
on-time departures
-
-
-
-
-
-
Tower load by airport
- Volume, average delay, and departure reliability
-
-
-
- title: {show: false},
- tooltip: {trigger: 'item'},
- grid: {left: 82, right: 42, bottom: 58, top: 20},
- xAxis: {
- type: 'value',
- name: 'Flights',
- nameLocation: 'middle',
- nameGap: 34,
- axisLine: {show: false},
- axisTick: {show: false},
- splitLine: {lineStyle: {color: '#edf1f2'}},
- },
- yAxis: {
- type: 'category',
- inverse: true,
- axisLine: {show: false},
- axisTick: {show: false},
- encode: {y: 'airport'},
- },
- series: [{
- type: 'bar',
- encode: {x: 'flights', y: 'airport', tooltip: ['city', 'avg_delay', 'on_time_departure_rate']},
- label: {show: true, position: 'right', formatter: '{@city}', color: '#5e6a70'},
- itemStyle: {color: '#2f7d68', borderRadius: [0, 3, 3, 0]},
- }]
-
-
-
-
diff --git a/examples/flights/index.md b/examples/flights/index.md
index 89a93293..83c4c16d 100644
--- a/examples/flights/index.md
+++ b/examples/flights/index.md
@@ -1,147 +1,350 @@
---
-title: Flight Operations Overview
layout: dashboard
---
-```gsql flown
--- most of our charts only show stats from flights that actually flew
-from flights where not is_cancelled
-```
+
+
+```gsql totals
+from flights select
count() as flights,
- on_time_arrival_rate,
- cancellation_rate,
- avg(dep_delay) as avg_dep_delay,
- count(distinct destination) as destinations,
- round(avg(aircraft_age), 1) as avg_aircraft_age,
- round(avg(distance), 0) as avg_distance,
- '/carrier_detail?carrier=' || carriers.code as link
-order by flights desc
+ count(distinct carrier) as carriers,
+ count(distinct origin) as airports,
+ count(distinct tail_num) as aircraft
```
-
+
+
+
+
+
+
+
Contents
+
+
+
+
+
+
The Source Data
+
+
+
+
+ carriers
+ one airline
+ code · name · nickname
+
+
carrier
+
+ flights
+ one scheduled flight
+ dep_delay · arr_delay · cancelled · aircraft_age
+
+
origin · dest
+
+ airports
+ one FAA facility
+ code · city · state · lat / long · major
+
+
+
+
tail_num
+
+ aircraft
+ one registered tail number
+ tail_num · year_built · owner
+
+
model
+
+ aircraft_models
+ one aircraft model
+ manufacturer · model · seats · engines · speed
+
+
+
+
+
Fig. 1 — Five tables in /tables, joined into a star around flights.
+
+
+
+
Built with Graphene · GSQL models define the joins, dimensions, and measures used across every page.
+
+
diff --git a/examples/flights/carrier_detail.md b/examples/flights/pages/carrier_detail.md
similarity index 99%
rename from examples/flights/carrier_detail.md
rename to examples/flights/pages/carrier_detail.md
index 5a830346..b2498dd5 100644
--- a/examples/flights/carrier_detail.md
+++ b/examples/flights/pages/carrier_detail.md
@@ -157,7 +157,7 @@ select
aircraft_models.manufacturer as manufacturer,
aircraft_models.model as model,
year_built::text as year_built,
- count(distinct flights.id2) as flights_flown,
+ count(flights.id2) as flights_flown,
sum(flights.miles_flown) as miles_flown
order by flights_flown desc
limit 100
diff --git a/examples/flights/delay_factors.md b/examples/flights/pages/delay_factors.md
similarity index 100%
rename from examples/flights/delay_factors.md
rename to examples/flights/pages/delay_factors.md
diff --git a/examples/flights/pages/operations_overview.md b/examples/flights/pages/operations_overview.md
new file mode 100644
index 00000000..c758bc5f
--- /dev/null
+++ b/examples/flights/pages/operations_overview.md
@@ -0,0 +1,147 @@
+---
+title: Flight Operations Overview
+layout: dashboard
+---
+
+```gsql flown
+-- most of our charts only show stats from flights that actually flew
+from flights where not is_cancelled
+```
+
+
+
+
+
+
+
+
+```gsql performance_by_year
+from flights select date_trunc('year', dep_time), status, count() as flight_count order by year, status
+```
+
+
+
+
+
+
+```gsql delay_heatmap
+from flights
+where cancelled = 'N' and extract(hour from dep_time)::integer between 5 and 23
+select
+ case extract(hour from dep_time)::integer
+ when 5 then '5am' when 6 then '6am' when 7 then '7am' when 8 then '8am'
+ when 9 then '9am' when 10 then '10am' when 11 then '11am' when 12 then '12pm'
+ when 13 then '1pm' when 14 then '2pm' when 15 then '3pm' when 16 then '4pm'
+ when 17 then '5pm' when 18 then '6pm' when 19 then '7pm' when 20 then '8pm'
+ when 21 then '9pm' when 22 then '10pm' when 23 then '11pm'
+ end as hour_label,
+ case extract(dow from dep_time)::integer
+ when 0 then 'Sun' when 1 then 'Mon' when 2 then 'Tue' when 3 then 'Wed'
+ when 4 then 'Thu' when 5 then 'Fri' when 6 then 'Sat'
+ end as day_label,
+ round(avg(dep_delay), 1) as avg_delay
+order by day_label, hour_label
+```
+
+```sql airport_scatter
+from flown select origin as code,
+ round(avg(dep_delay), 1) as avg_dep_delay,
+ round(avg(arr_delay), 1) as avg_arr_delay,
+ round(count() / count(distinct extract(year from dep_time)::integer), 0) as avg_annual_flights
+having count() > 100
+```
+
+
+
+
+ title: {text: 'Avg Departure Delay by Hour & Day of Week (min)'},
+ tooltip: {trigger: 'item'},
+ visualMap: {
+ min: -7.5, max: 30,
+ calculable: true,
+ orient: 'horizontal',
+ left: 'center',
+ bottom: 4,
+ inRange: {color: ['#5B8F9E', '#e4eff3', '#D4A94C', '#C87F5A', '#C4868E', '#B87470']},
+ },
+ grid: {top: 20},
+ xAxis: {
+ type: 'category',
+ position: 'top',
+ data: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
+ },
+ yAxis: {
+ type: 'category',
+ inverse: true,
+ data: ['5am','6am','7am','8am','9am','10am','11am','12pm','1pm','2pm','3pm','4pm','5pm','6pm','7pm','8pm','9pm','10pm','11pm'],
+ },
+ series: [{
+ type: 'heatmap',
+ encode: {x: 'day_label', y: 'hour_label', value: 'avg_delay'},
+ label: {show: false},
+ }],
+
+
+
+ title: {text: 'Departure vs Arrival Delay by Airport'},
+ tooltip: {trigger: 'item'},
+ grid: {top: 20},
+ visualMap: {
+ dimension: 'avg_annual_flights',
+ type: 'continuous',
+ min: 0, max: 3000,
+ inRange: {symbolSize: [4, 32]},
+ show: false,
+ },
+ xAxis: {
+ type: 'value',
+ name: 'Avg Departure Delay (min)',
+ nameLocation: 'middle',
+ nameGap: 22,
+ axisLine: {show: false},
+ axisTick: {show: false},
+ },
+ yAxis: {
+ type: 'value',
+ name: 'Avg Arrival Delay (min)',
+ nameLocation: 'middle',
+ nameGap: 20,
+ axisLine: {show: false},
+ axisTick: {show: false},
+ },
+ series: [{
+ type: 'scatter',
+ encode: {x: 'avg_dep_delay', y: 'avg_arr_delay', itemName: 'code', tooltip: 'avg_annual_flights'},
+ itemStyle: {opacity: 0.8},
+ tooltip: {formatter: '{b}'},
+ }]
+
+
+
+```gsql top_carriers
+from flights
+select
+ carriers.nickname as carrier,
+ count() as flights,
+ on_time_arrival_rate,
+ cancellation_rate,
+ avg(dep_delay) as avg_dep_delay,
+ count(distinct destination) as destinations,
+ round(avg(aircraft_age), 1) as avg_aircraft_age,
+ round(avg(distance), 0) as avg_distance,
+ '/pages/carrier_detail?carrier=' || carriers.code as link
+order by flights desc
+```
+
+
diff --git a/examples/flights/tables/aircraft.gsql b/examples/flights/tables/aircraft.gsql
index 81b61aad..704e15d4 100644
--- a/examples/flights/tables/aircraft.gsql
+++ b/examples/flights/tables/aircraft.gsql
@@ -15,7 +15,7 @@ table aircraft (
aircraft_engine_code VARCHAR
aircraft_type_id BIGINT
aircraft_engine_type_id BIGINT
- year_built BIGINT
+ year_built BIGINT -- Contains zeros when unknown; use year_built_safe instead #timeGrain=year #hide
/* Registration & status */
@@ -44,4 +44,8 @@ table aircraft (
join one aircraft_models on aircraft_model_code = aircraft_models.aircraft_model_code
join many flights on tail_num = flights.tail_num
+
+ /* Dimensions */
+
+ year_built_safe: nullif(year_built, 0) #timeGrain=year
)
diff --git a/examples/flights/tables/aircraft_models.gsql b/examples/flights/tables/aircraft_models.gsql
index 9f4c653a..1dc4fbfc 100644
--- a/examples/flights/tables/aircraft_models.gsql
+++ b/examples/flights/tables/aircraft_models.gsql
@@ -10,8 +10,8 @@ table aircraft_models (
amateur BIGINT -- Amateur-built indicator (0 = no, 1 = yes)
engines BIGINT -- Number of engines
seats BIGINT -- Number of passenger seats (0 for cargo-only or single-seat)
- weight BIGINT -- Maximum takeoff weight, in pounds
- speed BIGINT -- Maximum speed, in knots
+ weight BIGINT -- Maximum takeoff weight, in pounds #unit=pounds
+ speed BIGINT -- Maximum speed, in knots #unit=knots
/* Join relationships */
diff --git a/examples/flights/tables/airports.gsql b/examples/flights/tables/airports.gsql
index 070af6cf..bcc2ad0f 100644
--- a/examples/flights/tables/airports.gsql
+++ b/examples/flights/tables/airports.gsql
@@ -24,8 +24,8 @@ table airports (
state VARCHAR
longitude DOUBLE
latitude DOUBLE
- elevation BIGINT -- Elevation above sea level, in feet
- cbd_dist BIGINT -- Distance to central business district, in miles
+ elevation BIGINT -- Elevation above sea level, in feet #unit=feet
+ cbd_dist BIGINT -- Distance to central business district, in miles #unit=miles
cbd_dir VARCHAR -- Compass direction to CBD (e.g., 'N', 'SW', 'SE')
/* FAA / regulatory */
diff --git a/examples/flights/tables/flights.gsql b/examples/flights/tables/flights.gsql
index aea15ceb..9fb82258 100644
--- a/examples/flights/tables/flights.gsql
+++ b/examples/flights/tables/flights.gsql
@@ -6,24 +6,24 @@ table flights (
id2 BIGINT
carrier VARCHAR -- Airline carrier code, e.g., 'AA', 'UA', 'DL'
- flight_num VARCHAR -- Flight number assigned by the carrier
- tail_num VARCHAR -- Aircraft registration
+ flight_num VARCHAR
+ tail_num VARCHAR
/* Route */
origin VARCHAR -- IATA code of origin airport
destination VARCHAR -- IATA code of destination airport
- distance BIGINT -- Distance between origin and destination, in miles. Not to be confused with miles_flown
+ distance BIGINT -- Distance between origin and destination, in miles. Not to be confused with miles_flown #unit=miles
/* Times & delays (minutes) */
- dep_time TIMESTAMP -- Actual departure time
- arr_time TIMESTAMP -- Actual arrival time
- flight_time BIGINT -- Scheduled time in the air, excluding taxi
- taxi_out BIGINT -- Taxi time before takeoff
- taxi_in BIGINT -- Taxi time after landing
- dep_delay BIGINT -- Departure delay; negative = early, positive = late
- arr_delay BIGINT -- Arrival delay; negative = early, positive = late
+ dep_time TIMESTAMP -- Actual departure time after delay
+ arr_time TIMESTAMP -- Actual arrival time after delay
+ flight_time BIGINT -- Scheduled time in the air, excluding taxi #unit=minutes
+ taxi_out BIGINT -- Taxi time before takeoff #unit=minutes
+ taxi_in BIGINT -- Taxi time after landing #unit=minutes
+ dep_delay BIGINT -- Departure delay; negative = early, positive = late #unit=minutes
+ arr_delay BIGINT -- Arrival delay; negative = early, positive = late #unit=minutes
/* Status */
@@ -43,8 +43,10 @@ table flights (
is_cancelled: cancelled = 'Y'
is_cancelled_or_diverted: cancelled = 'Y' or diverted = 'Y'
-- Distance actually flown; cancelled/diverted flights count as 0
- miles_flown: case when is_cancelled_or_diverted then 0 else distance end
- aircraft_age: YEAR(dep_time)::float - aircraft.year_built
+ miles_flown: case when is_cancelled_or_diverted then 0 else distance end #unit=miles
+ aircraft_age: YEAR(dep_time)::float - aircraft.year_built #unit=years
+ scheduled_dep_time: dep_time - interval dep_delay minute
+ scheduled_arr_time: arr_time - interval arr_delay minute
status: case
when cancelled = 'Y' then 'Cancelled'
diff --git a/examples/flights_empty/AGENTS.md b/examples/flights_empty/AGENTS.md
deleted file mode 100644
index 615c1266..00000000
--- a/examples/flights_empty/AGENTS.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# RULES
-
-- Graphene contains languages and tools that you do not already know.
-- Before writing code in this directory, you MUST read `@../../docs/base.md` **in its entirety**.
-- You MUST also read relevant reference docs in `@../../docs/references/*.md` before implementing or editing related functionality.
-- Treat reference docs as required context, not optional reading.
-- If a task touches multiple areas (for example: GSQL + chart components), read all applicable reference files first.
-- If unsure which reference applies, start with `@../../docs/references/gsql.md`, then load additional references based on the components/functions used.
-- You will be docked for writing code here without completing the required documentation reading.
-
-## Reference docs
-
-- Core overview: `@../../docs/base.md`
-- CLI usage: `@../../docs/cli.md`
-- Best practices: `@../../docs/best-practices.md`
-- Detailed feature/component references: `@../../docs/references/*.md`
-
-# About this data
-
-This is a Graphene project covering FAA flight data from 2000 to 2005. You can find the Graphene tables in @./tables.
diff --git a/examples/flights_empty/package.json b/examples/flights_empty/package.json
deleted file mode 100644
index f8879e6e..00000000
--- a/examples/flights_empty/package.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "name": "example-flights-empty",
- "version": "0.0.1",
- "type": "module",
- "scripts": {
- "graphene": "node ../../cli/cli.ts",
- "serve": "npm run graphene serve",
- "compile": "npm run graphene compile",
- "run": "npm run graphene run"
- },
- "dependencies": {
- "@duckdb/node-api": "1.5.3-r.3",
- "@graphenedata/cli": "workspace:*"
- },
- "engines": {
- "node": ">=24.0.0",
- "npm": ">=7.0.0"
- },
- "graphene": {
- "dialect": "duckdb",
- "envFile": [
- ".env",
- "../../.env",
- "../../../.env"
- ]
- }
-}
diff --git a/examples/flights_empty/tables/aircraft.gsql b/examples/flights_empty/tables/aircraft.gsql
deleted file mode 100644
index 1a7cf8f2..00000000
--- a/examples/flights_empty/tables/aircraft.gsql
+++ /dev/null
@@ -1,27 +0,0 @@
-table aircraft (
- id BIGINT,
- tail_num VARCHAR,
- aircraft_serial VARCHAR,
- aircraft_model_code VARCHAR,
- aircraft_engine_code VARCHAR,
- year_built BIGINT,
- aircraft_type_id BIGINT,
- aircraft_engine_type_id BIGINT,
- registrant_type_id BIGINT,
- name VARCHAR,
- address1 VARCHAR,
- address2 VARCHAR,
- city VARCHAR,
- state VARCHAR,
- zip VARCHAR,
- region VARCHAR,
- county VARCHAR,
- country VARCHAR,
- certification VARCHAR,
- status_code VARCHAR,
- mode_s_code VARCHAR,
- fract_owner VARCHAR,
- last_action_date DATE,
- cert_issue_date DATE,
- air_worth_date DATE
-);
diff --git a/examples/flights_empty/tables/aircraft_models.gsql b/examples/flights_empty/tables/aircraft_models.gsql
deleted file mode 100644
index d0c419d6..00000000
--- a/examples/flights_empty/tables/aircraft_models.gsql
+++ /dev/null
@@ -1,13 +0,0 @@
-table aircraft_models (
- aircraft_model_code VARCHAR,
- manufacturer VARCHAR,
- model VARCHAR,
- aircraft_type_id BIGINT,
- aircraft_engine_type_id BIGINT,
- aircraft_category_id BIGINT,
- amateur BIGINT,
- engines BIGINT,
- seats BIGINT,
- weight BIGINT,
- speed BIGINT
-);
diff --git a/examples/flights_empty/tables/airports.gsql b/examples/flights_empty/tables/airports.gsql
deleted file mode 100644
index 42aaa037..00000000
--- a/examples/flights_empty/tables/airports.gsql
+++ /dev/null
@@ -1,29 +0,0 @@
-table airports (
- id BIGINT,
- code VARCHAR,
- site_number VARCHAR,
- fac_type VARCHAR,
- fac_use VARCHAR,
- faa_region VARCHAR,
- faa_dist VARCHAR,
- city VARCHAR,
- county VARCHAR,
- state VARCHAR,
- full_name VARCHAR,
- own_type VARCHAR,
- longitude DOUBLE,
- latitude DOUBLE,
- elevation BIGINT,
- aero_cht VARCHAR,
- cbd_dist BIGINT,
- cbd_dir VARCHAR,
- act_date VARCHAR,
- cert VARCHAR,
- fed_agree VARCHAR,
- cust_intl VARCHAR,
- c_ldg_rts VARCHAR,
- joint_use VARCHAR,
- mil_rts VARCHAR,
- cntl_twr VARCHAR,
- major VARCHAR
-);
diff --git a/examples/flights_empty/tables/carriers.gsql b/examples/flights_empty/tables/carriers.gsql
deleted file mode 100644
index 4e00cfea..00000000
--- a/examples/flights_empty/tables/carriers.gsql
+++ /dev/null
@@ -1,5 +0,0 @@
-table carriers (
- code VARCHAR,
- name VARCHAR,
- nickname VARCHAR
-);
diff --git a/examples/flights_empty/tables/flights.gsql b/examples/flights_empty/tables/flights.gsql
deleted file mode 100644
index 6b885d29..00000000
--- a/examples/flights_empty/tables/flights.gsql
+++ /dev/null
@@ -1,18 +0,0 @@
-table flights (
- carrier VARCHAR,
- origin VARCHAR,
- destination VARCHAR,
- flight_num VARCHAR,
- flight_time BIGINT,
- tail_num VARCHAR,
- dep_time TIMESTAMP,
- arr_time TIMESTAMP,
- dep_delay BIGINT,
- arr_delay BIGINT,
- taxi_out BIGINT,
- taxi_in BIGINT,
- distance BIGINT,
- cancelled VARCHAR,
- diverted VARCHAR,
- id2 BIGINT
-);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ec17c50d..9eda79fa 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -13,13 +13,13 @@ importers:
devDependencies:
'@eslint/compat':
specifier: ^2.0.2
- version: 2.0.3(eslint@10.2.0(supports-color@8.1.1))
+ version: 2.0.3(eslint@10.2.0)
'@eslint/js':
specifier: ^10.0.1
- version: 10.0.1(eslint@10.2.0(supports-color@8.1.1))
+ version: 10.0.1(eslint@10.2.0)
'@stylistic/eslint-plugin':
specifier: ^5.9.0
- version: 5.10.0(eslint@10.2.0(supports-color@8.1.1))
+ version: 5.10.0(eslint@10.2.0)
'@types/fs-extra':
specifier: ^11.0.4
version: 11.0.4
@@ -34,13 +34,13 @@ importers:
version: 17.3.1
eslint:
specifier: ^10.2.0
- version: 10.2.0(supports-color@8.1.1)
+ version: 10.2.0
eslint-plugin-prefer-let:
specifier: ^4.0.1
version: 4.1.0
eslint-plugin-svelte:
specifier: ^3.17.1
- version: 3.17.1(eslint@10.2.0(supports-color@8.1.1))(svelte@5.55.7(@typescript-eslint/types@8.56.1))
+ version: 3.17.1(eslint@10.2.0)(svelte@5.55.7(@typescript-eslint/types@8.56.1))
glob:
specifier: ^13.0.1
version: 13.0.6
@@ -55,7 +55,7 @@ importers:
version: 5.9.3
typescript-eslint:
specifier: ^8.54.0
- version: 8.56.1(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)
+ version: 8.56.1(eslint@10.2.0)(typescript@5.9.3)
vitest:
specifier: 4.0.18
version: 4.0.18(@types/node@22.19.15)
@@ -254,15 +254,6 @@ importers:
specifier: workspace:*
version: link:../../cli
- examples/flights_empty:
- dependencies:
- '@duckdb/node-api':
- specifier: 1.5.3-r.3
- version: 1.5.3-r.3
- '@graphenedata/cli':
- specifier: workspace:*
- version: link:../../cli
-
examples/motherduck:
dependencies:
'@duckdb/node-api':
@@ -4381,20 +4372,20 @@ snapshots:
'@esbuild/win32-x64@0.27.3':
optional: true
- '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0(supports-color@8.1.1))':
+ '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0)':
dependencies:
- eslint: 10.2.0(supports-color@8.1.1)
+ eslint: 10.2.0
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.2': {}
- '@eslint/compat@2.0.3(eslint@10.2.0(supports-color@8.1.1))':
+ '@eslint/compat@2.0.3(eslint@10.2.0)':
dependencies:
'@eslint/core': 1.1.1
optionalDependencies:
- eslint: 10.2.0(supports-color@8.1.1)
+ eslint: 10.2.0
- '@eslint/config-array@0.23.5(supports-color@8.1.1)':
+ '@eslint/config-array@0.23.5':
dependencies:
'@eslint/object-schema': 3.0.5
debug: 4.4.3(supports-color@8.1.1)
@@ -4414,9 +4405,9 @@ snapshots:
dependencies:
'@types/json-schema': 7.0.15
- '@eslint/js@10.0.1(eslint@10.2.0(supports-color@8.1.1))':
+ '@eslint/js@10.0.1(eslint@10.2.0)':
optionalDependencies:
- eslint: 10.2.0(supports-color@8.1.1)
+ eslint: 10.2.0
'@eslint/object-schema@3.0.5': {}
@@ -5048,11 +5039,11 @@ snapshots:
'@standard-schema/spec@1.1.0': {}
- '@stylistic/eslint-plugin@5.10.0(eslint@10.2.0(supports-color@8.1.1))':
+ '@stylistic/eslint-plugin@5.10.0(eslint@10.2.0)':
dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(supports-color@8.1.1))
+ '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0)
'@typescript-eslint/types': 8.56.1
- eslint: 10.2.0(supports-color@8.1.1)
+ eslint: 10.2.0
eslint-visitor-keys: 4.2.1
espree: 10.4.0
estraverse: 5.3.0
@@ -5168,15 +5159,15 @@ snapshots:
dependencies:
'@types/node': 22.19.15
- '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)':
+ '@typescript-eslint/eslint-plugin@8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.2.0)(typescript@5.9.3))(eslint@10.2.0)(typescript@5.9.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 8.56.1(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.56.1(eslint@10.2.0)(typescript@5.9.3)
'@typescript-eslint/scope-manager': 8.56.1
- '@typescript-eslint/type-utils': 8.56.1(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)
- '@typescript-eslint/utils': 8.56.1(eslint@10.2.0(supports-color@8.1.1))(typescript@5.9.3)
+ '@typescript-eslint/type-utils': 8.56.1(eslint@10.2.0)(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.56.1(eslint@10.2.0)(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.56.1
- eslint: 10.2.0(supports-color@8.1.1)
+ eslint: 10.2.0
ignore: 7.0.5
natural-compare: 1.4.0
ts-api-utils: 2.4.0(typescript@5.9.3)
@@ -5184,14 +5175,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.56.1(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)':
+ '@typescript-eslint/parser@8.56.1(eslint@10.2.0)(typescript@5.9.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.56.1
'@typescript-eslint/types': 8.56.1
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
'@typescript-eslint/visitor-keys': 8.56.1
debug: 4.4.3(supports-color@8.1.1)
- eslint: 10.2.0(supports-color@8.1.1)
+ eslint: 10.2.0
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -5214,13 +5205,13 @@ snapshots:
dependencies:
typescript: 5.9.3
- '@typescript-eslint/type-utils@8.56.1(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)':
+ '@typescript-eslint/type-utils@8.56.1(eslint@10.2.0)(typescript@5.9.3)':
dependencies:
'@typescript-eslint/types': 8.56.1
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
- '@typescript-eslint/utils': 8.56.1(eslint@10.2.0(supports-color@8.1.1))(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.56.1(eslint@10.2.0)(typescript@5.9.3)
debug: 4.4.3(supports-color@8.1.1)
- eslint: 10.2.0(supports-color@8.1.1)
+ eslint: 10.2.0
ts-api-utils: 2.4.0(typescript@5.9.3)
typescript: 5.9.3
transitivePeerDependencies:
@@ -5243,13 +5234,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.56.1(eslint@10.2.0(supports-color@8.1.1))(typescript@5.9.3)':
+ '@typescript-eslint/utils@8.56.1(eslint@10.2.0)(typescript@5.9.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(supports-color@8.1.1))
+ '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0)
'@typescript-eslint/scope-manager': 8.56.1
'@typescript-eslint/types': 8.56.1
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
- eslint: 10.2.0(supports-color@8.1.1)
+ eslint: 10.2.0
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -5746,11 +5737,11 @@ snapshots:
dependencies:
requireindex: 1.2.0
- eslint-plugin-svelte@3.17.1(eslint@10.2.0(supports-color@8.1.1))(svelte@5.55.7(@typescript-eslint/types@8.56.1)):
+ eslint-plugin-svelte@3.17.1(eslint@10.2.0)(svelte@5.55.7(@typescript-eslint/types@8.56.1)):
dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(supports-color@8.1.1))
+ '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0)
'@jridgewell/sourcemap-codec': 1.5.5
- eslint: 10.2.0(supports-color@8.1.1)
+ eslint: 10.2.0
esutils: 2.0.3
globals: 16.5.0
known-css-properties: 0.37.0
@@ -5782,11 +5773,11 @@ snapshots:
eslint-visitor-keys@5.0.1: {}
- eslint@10.2.0(supports-color@8.1.1):
+ eslint@10.2.0:
dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(supports-color@8.1.1))
+ '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0)
'@eslint-community/regexpp': 4.12.2
- '@eslint/config-array': 0.23.5(supports-color@8.1.1)
+ '@eslint/config-array': 0.23.5
'@eslint/config-helpers': 0.5.5
'@eslint/core': 1.2.1
'@eslint/plugin-kit': 0.7.1
@@ -6961,13 +6952,13 @@ snapshots:
dependencies:
prelude-ls: 1.2.1
- typescript-eslint@8.56.1(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3):
+ typescript-eslint@8.56.1(eslint@10.2.0)(typescript@5.9.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3))(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)
- '@typescript-eslint/parser': 8.56.1(eslint@10.2.0(supports-color@8.1.1))(supports-color@8.1.1)(typescript@5.9.3)
+ '@typescript-eslint/eslint-plugin': 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.2.0)(typescript@5.9.3))(eslint@10.2.0)(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.56.1(eslint@10.2.0)(typescript@5.9.3)
'@typescript-eslint/typescript-estree': 8.56.1(typescript@5.9.3)
- '@typescript-eslint/utils': 8.56.1(eslint@10.2.0(supports-color@8.1.1))(typescript@5.9.3)
- eslint: 10.2.0(supports-color@8.1.1)
+ '@typescript-eslint/utils': 8.56.1(eslint@10.2.0)(typescript@5.9.3)
+ eslint: 10.2.0
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
diff --git a/ui/tests/connectionAuth.test.ts b/ui/tests/connectionAuth.test.ts
index c3a1bef8..bbb00081 100644
--- a/ui/tests/connectionAuth.test.ts
+++ b/ui/tests/connectionAuth.test.ts
@@ -16,10 +16,10 @@ async function loginToSnowflakeOAuth(page: Page, url: string, opts: {username: s
await inputs.nth(1).fill(opts.password)
} else {
await inputs.first().fill(opts.username)
- await page.getByRole('button', {name: /continue|next|log in|sign in/i}).click()
+ await page.getByRole('button', {name: /^(continue|next|log in|sign in)$/i}).click()
await page.locator('input[type="password"], input[autocomplete="current-password"]').first().fill(opts.password)
}
- await page.getByRole('button', {name: /continue|next|log in|sign in/i}).click()
+ await page.getByRole('button', {name: /^(continue|next|log in|sign in)$/i}).click()
let mfaInput = page.locator('input[autocomplete="one-time-code"], input[name*="passcode" i], input[name*="code" i]').first()
await mfaInput.waitFor({state: 'visible', timeout: 60_000})
diff --git a/ui/tests/markdown.test.ts b/ui/tests/markdown.test.ts
index 0479f1e4..c2f3505a 100644
--- a/ui/tests/markdown.test.ts
+++ b/ui/tests/markdown.test.ts
@@ -355,7 +355,7 @@ test('allows collapsing and expanding folders', async ({server, page}) => {
await page.getByRole('button', {name: 'Open navigation'}).hover()
let nav = page.getByRole('navigation')
// The folder's index.md shows up as its own "Home" page routed to the folder path.
- await expect(nav.getByRole('link', {name: 'Home'})).toHaveAttribute('href', /\/other$/)
+ await expect(nav.locator('a[href="/other"]', {hasText: 'Home'})).toHaveAttribute('href', /\/other$/)
let otherToggle = nav.locator('[data-folder-toggle="other"]')
await otherToggle.click()
await expect(nav.getByRole('link', {name: 'Third'})).toBeHidden()
diff --git a/ui/tests/snapshots/markdown.test.ts/expanded-nav.png b/ui/tests/snapshots/markdown.test.ts/expanded-nav.png
index 668caa19..cc061e28 100644
--- a/ui/tests/snapshots/markdown.test.ts/expanded-nav.png
+++ b/ui/tests/snapshots/markdown.test.ts/expanded-nav.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e92302266fc57b48d6f5c4262b468ff5cf42ee76775434de21cc213f147fba80
-size 35897
+oid sha256:2e66bdddb99ddb0daa58c93430dbbc4586189e62484a9e703fdab3936694dcfe
+size 27959
diff --git a/ui/tests/snapshots/run-examples.test.ts/example-flights-carrier-detail.png b/ui/tests/snapshots/run-examples.test.ts/example-flights-carrier-detail.png
deleted file mode 100644
index 1796434f..00000000
--- a/ui/tests/snapshots/run-examples.test.ts/example-flights-carrier-detail.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:c921370c411d20910f7ee80ac1af22dc9fe9185e4ca7adac37f7420f3a755475
-size 98055
diff --git a/ui/tests/snapshots/run-examples.test.ts/example-flights-control-room.png b/ui/tests/snapshots/run-examples.test.ts/example-flights-control-room.png
deleted file mode 100644
index 8efdac3b..00000000
--- a/ui/tests/snapshots/run-examples.test.ts/example-flights-control-room.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8b4ae312291a5b35b6fcab34b88e15d60b6cc8c806211573a1e758d3c5866080
-size 200564
diff --git a/ui/tests/snapshots/run-examples.test.ts/example-flights-index.png b/ui/tests/snapshots/run-examples.test.ts/example-flights-index.png
index 32ccc761..e28b9b46 100644
--- a/ui/tests/snapshots/run-examples.test.ts/example-flights-index.png
+++ b/ui/tests/snapshots/run-examples.test.ts/example-flights-index.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:e911e85681087a333b35c82a861b9baf4b2671fd04aca2a3436cb864290daa54
-size 57812
+oid sha256:b8779a9e54bb9cf3221d51550e1e5b2fb7304f04640a8c09a9e00d681507f61b
+size 74652
diff --git a/ui/tests/snapshots/run-examples.test.ts/example-flights-pages-carrier-detail.png b/ui/tests/snapshots/run-examples.test.ts/example-flights-pages-carrier-detail.png
new file mode 100644
index 00000000..a425edcc
--- /dev/null
+++ b/ui/tests/snapshots/run-examples.test.ts/example-flights-pages-carrier-detail.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:dd124b176b7b18488afc0bbfc83526c8e145c7628d2db5c6a0d62e0a3cbfc8ba
+size 98034
diff --git a/ui/tests/snapshots/run-examples.test.ts/example-flights-delay-factors.png b/ui/tests/snapshots/run-examples.test.ts/example-flights-pages-delay-factors.png
similarity index 100%
rename from ui/tests/snapshots/run-examples.test.ts/example-flights-delay-factors.png
rename to ui/tests/snapshots/run-examples.test.ts/example-flights-pages-delay-factors.png
diff --git a/ui/tests/snapshots/run-examples.test.ts/example-flights-pages-operations-overview.png b/ui/tests/snapshots/run-examples.test.ts/example-flights-pages-operations-overview.png
new file mode 100644
index 00000000..32ccc761
--- /dev/null
+++ b/ui/tests/snapshots/run-examples.test.ts/example-flights-pages-operations-overview.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e911e85681087a333b35c82a861b9baf4b2671fd04aca2a3436cb864290daa54
+size 57812