@definite-app/data-apps 1.0.0
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/CLAUDE.md +686 -0
- package/LICENSE +201 -0
- package/README.md +643 -0
- package/build.mjs +459 -0
- package/examples/_refined_demo/app.json +15 -0
- package/examples/_refined_demo/data/sample.parquet +0 -0
- package/examples/_refined_demo/gen_preview_data.py +59 -0
- package/examples/_refined_demo/preview-data.json +13 -0
- package/examples/_refined_demo/src/App.tsx +188 -0
- package/examples/_refined_demo/src/main.tsx +12 -0
- package/examples/loan-portfolio/app.json +31 -0
- package/examples/loan-portfolio/data/loan_book.parquet +0 -0
- package/examples/loan-portfolio/gen_preview_data.py +454 -0
- package/examples/loan-portfolio/preview-data.json +84 -0
- package/examples/loan-portfolio/src/App.tsx +1103 -0
- package/examples/loan-portfolio/src/main.tsx +12 -0
- package/examples/revenue-explorer/app.json +23 -0
- package/examples/revenue-explorer/data/transactions.parquet +0 -0
- package/examples/revenue-explorer/gen_preview_data.py +129 -0
- package/examples/revenue-explorer/preview-data.json +49 -0
- package/examples/revenue-explorer/src/App.tsx +527 -0
- package/examples/revenue-explorer/src/main.tsx +12 -0
- package/package.json +55 -0
- package/preview.mjs +35 -0
- package/runtime/definite-runtime.tsx +5934 -0
- package/scripts/headless-smoke.mjs +196 -0
- package/templates/blank/app.json +15 -0
- package/templates/blank/src/App.tsx +41 -0
- package/templates/blank/src/main.tsx +12 -0
- package/templates/refined/app.json +15 -0
- package/templates/refined/src/App.tsx +198 -0
- package/templates/refined/src/main.tsx +12 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { createRoot } from "react-dom/client";
|
|
3
|
+
|
|
4
|
+
import App from "./App";
|
|
5
|
+
|
|
6
|
+
const rootElement = document.getElementById("root");
|
|
7
|
+
|
|
8
|
+
if (!rootElement) {
|
|
9
|
+
throw new Error("Missing #root mount element");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
createRoot(rootElement).render(<App />);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"name": "Revenue Explorer",
|
|
4
|
+
"entry": "src/main.tsx",
|
|
5
|
+
"resources": {
|
|
6
|
+
"transactions": {
|
|
7
|
+
"kind": "dataset",
|
|
8
|
+
"source": {
|
|
9
|
+
"type": "sql",
|
|
10
|
+
"sql": "SELECT id AS transactionId, STRFTIME(created_at, '%Y-%m-%d') AS transactionDate, amount::DOUBLE AS amount, branch_name AS branchName, status FROM LAKE.SCHEMA.transactions LIMIT 200000"
|
|
11
|
+
},
|
|
12
|
+
"public": false
|
|
13
|
+
},
|
|
14
|
+
"branches": {
|
|
15
|
+
"kind": "json",
|
|
16
|
+
"source": {
|
|
17
|
+
"type": "sql",
|
|
18
|
+
"sql": "SELECT branch_id AS branchId, branch_name AS branchName FROM LAKE.SCHEMA.branches ORDER BY 2 LIMIT 3000"
|
|
19
|
+
},
|
|
20
|
+
"public": false
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env -S uv run
|
|
2
|
+
# /// script
|
|
3
|
+
# requires-python = ">=3.10"
|
|
4
|
+
# dependencies = ["duckdb", "pyarrow"]
|
|
5
|
+
# ///
|
|
6
|
+
"""Generate realistic demo transactions and write both a parquet sidecar
|
|
7
|
+
(data/transactions.parquet) and an expanded preview-data.json so the starter
|
|
8
|
+
data app has non-trivial data to filter.
|
|
9
|
+
|
|
10
|
+
Run: uv run gen_preview_data.py
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import random
|
|
15
|
+
from datetime import date, timedelta
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
import duckdb
|
|
19
|
+
import pyarrow as pa
|
|
20
|
+
import pyarrow.parquet as pq
|
|
21
|
+
|
|
22
|
+
HERE = Path(__file__).parent
|
|
23
|
+
DATA_DIR = HERE / "data"
|
|
24
|
+
PARQUET_PATH = DATA_DIR / "transactions.parquet"
|
|
25
|
+
PREVIEW_PATH = HERE / "preview-data.json"
|
|
26
|
+
|
|
27
|
+
BRANCHES = [
|
|
28
|
+
("AUS", "Austin"),
|
|
29
|
+
("BOS", "Boston"),
|
|
30
|
+
("CHI", "Chicago"),
|
|
31
|
+
("DEN", "Denver"),
|
|
32
|
+
("MIA", "Miami"),
|
|
33
|
+
("NSH", "Nashville"),
|
|
34
|
+
("SEA", "Seattle"),
|
|
35
|
+
("SFO", "San Francisco"),
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
STATUSES = ["Funded", "Pending", "Review"]
|
|
39
|
+
STATUS_WEIGHTS = [0.70, 0.20, 0.10]
|
|
40
|
+
|
|
41
|
+
# ~10k rows spanning 2024-01-01 through 2026-12-31 so every preset has coverage
|
|
42
|
+
START = date(2024, 1, 1)
|
|
43
|
+
END = date(2026, 12, 31)
|
|
44
|
+
N_ROWS = 10000
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def gen_rows() -> list[dict]:
|
|
48
|
+
random.seed(42)
|
|
49
|
+
rows: list[dict] = []
|
|
50
|
+
# Give each branch its own baseline so revenue shapes look different
|
|
51
|
+
branch_bias = {code: random.uniform(0.7, 1.4) for code, _ in BRANCHES}
|
|
52
|
+
span = (END - START).days
|
|
53
|
+
for i in range(N_ROWS):
|
|
54
|
+
day_offset = random.randint(0, span)
|
|
55
|
+
d = START + timedelta(days=day_offset)
|
|
56
|
+
code, name = random.choice(BRANCHES)
|
|
57
|
+
status = random.choices(STATUSES, weights=STATUS_WEIGHTS, k=1)[0]
|
|
58
|
+
base = random.lognormvariate(7.2, 0.55) # ~$1000–$3000 typical, long tail
|
|
59
|
+
amount = round(base * branch_bias[code], 2)
|
|
60
|
+
rows.append(
|
|
61
|
+
{
|
|
62
|
+
"transactionId": f"TXN-{100000 + i}",
|
|
63
|
+
"transactionDate": d.isoformat(),
|
|
64
|
+
"amount": amount,
|
|
65
|
+
"branchName": name,
|
|
66
|
+
"status": status,
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
rows.sort(key=lambda r: r["transactionDate"])
|
|
70
|
+
return rows
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def write_parquet(rows: list[dict]) -> None:
|
|
74
|
+
DATA_DIR.mkdir(parents=True, exist_ok=True)
|
|
75
|
+
table = pa.Table.from_pylist(
|
|
76
|
+
rows,
|
|
77
|
+
schema=pa.schema(
|
|
78
|
+
[
|
|
79
|
+
("transactionId", pa.string()),
|
|
80
|
+
("transactionDate", pa.string()),
|
|
81
|
+
("amount", pa.float64()),
|
|
82
|
+
("branchName", pa.string()),
|
|
83
|
+
("status", pa.string()),
|
|
84
|
+
]
|
|
85
|
+
),
|
|
86
|
+
)
|
|
87
|
+
pq.write_table(table, PARQUET_PATH, compression="zstd")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def write_preview_json() -> None:
|
|
91
|
+
# References the parquet file; build.mjs inlines it as base64 at bundle time
|
|
92
|
+
# so the runtime loads it via DuckDB WASM read_parquet, not JSON parsing.
|
|
93
|
+
payload = {
|
|
94
|
+
"context": {
|
|
95
|
+
"publicMode": False,
|
|
96
|
+
"driveFile": "preview://data-apps/starter",
|
|
97
|
+
"appVersion": "v2",
|
|
98
|
+
},
|
|
99
|
+
"datasets": {
|
|
100
|
+
"transactions": {"file": "data/transactions.parquet", "format": "parquet"},
|
|
101
|
+
},
|
|
102
|
+
"resources": {
|
|
103
|
+
"branches": [{"branchId": code, "branchName": name} for code, name in BRANCHES],
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
PREVIEW_PATH.write_text(json.dumps(payload, indent=2) + "\n")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def report(rows: list[dict]) -> None:
|
|
110
|
+
con = duckdb.connect()
|
|
111
|
+
con.register("r", pa.Table.from_pylist(rows))
|
|
112
|
+
stats = con.execute(
|
|
113
|
+
"SELECT COUNT(*) AS n, MIN(transactionDate) AS min_d, MAX(transactionDate) AS max_d, "
|
|
114
|
+
"SUM(amount)::DOUBLE AS total, COUNT(DISTINCT branchName) AS branches FROM r"
|
|
115
|
+
).fetchone()
|
|
116
|
+
print(f"rows={stats[0]} dates={stats[1]}..{stats[2]} branches={stats[4]} total=${stats[3]:,.0f}")
|
|
117
|
+
print(f"parquet bytes: {PARQUET_PATH.stat().st_size:,}")
|
|
118
|
+
print(f"preview-data.json bytes: {PREVIEW_PATH.stat().st_size:,}")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def main() -> None:
|
|
122
|
+
rows = gen_rows()
|
|
123
|
+
write_parquet(rows)
|
|
124
|
+
write_preview_json()
|
|
125
|
+
report(rows)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
if __name__ == "__main__":
|
|
129
|
+
main()
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"context": {
|
|
3
|
+
"publicMode": false,
|
|
4
|
+
"driveFile": "preview://data-apps/starter",
|
|
5
|
+
"appVersion": "v2"
|
|
6
|
+
},
|
|
7
|
+
"datasets": {
|
|
8
|
+
"transactions": {
|
|
9
|
+
"file": "data/transactions.parquet",
|
|
10
|
+
"format": "parquet"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"resources": {
|
|
14
|
+
"branches": [
|
|
15
|
+
{
|
|
16
|
+
"branchId": "AUS",
|
|
17
|
+
"branchName": "Austin"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"branchId": "BOS",
|
|
21
|
+
"branchName": "Boston"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"branchId": "CHI",
|
|
25
|
+
"branchName": "Chicago"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"branchId": "DEN",
|
|
29
|
+
"branchName": "Denver"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"branchId": "MIA",
|
|
33
|
+
"branchName": "Miami"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"branchId": "NSH",
|
|
37
|
+
"branchName": "Nashville"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"branchId": "SEA",
|
|
41
|
+
"branchName": "Seattle"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"branchId": "SFO",
|
|
45
|
+
"branchName": "San Francisco"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|