@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.
Files changed (32) hide show
  1. package/CLAUDE.md +686 -0
  2. package/LICENSE +201 -0
  3. package/README.md +643 -0
  4. package/build.mjs +459 -0
  5. package/examples/_refined_demo/app.json +15 -0
  6. package/examples/_refined_demo/data/sample.parquet +0 -0
  7. package/examples/_refined_demo/gen_preview_data.py +59 -0
  8. package/examples/_refined_demo/preview-data.json +13 -0
  9. package/examples/_refined_demo/src/App.tsx +188 -0
  10. package/examples/_refined_demo/src/main.tsx +12 -0
  11. package/examples/loan-portfolio/app.json +31 -0
  12. package/examples/loan-portfolio/data/loan_book.parquet +0 -0
  13. package/examples/loan-portfolio/gen_preview_data.py +454 -0
  14. package/examples/loan-portfolio/preview-data.json +84 -0
  15. package/examples/loan-portfolio/src/App.tsx +1103 -0
  16. package/examples/loan-portfolio/src/main.tsx +12 -0
  17. package/examples/revenue-explorer/app.json +23 -0
  18. package/examples/revenue-explorer/data/transactions.parquet +0 -0
  19. package/examples/revenue-explorer/gen_preview_data.py +129 -0
  20. package/examples/revenue-explorer/preview-data.json +49 -0
  21. package/examples/revenue-explorer/src/App.tsx +527 -0
  22. package/examples/revenue-explorer/src/main.tsx +12 -0
  23. package/package.json +55 -0
  24. package/preview.mjs +35 -0
  25. package/runtime/definite-runtime.tsx +5934 -0
  26. package/scripts/headless-smoke.mjs +196 -0
  27. package/templates/blank/app.json +15 -0
  28. package/templates/blank/src/App.tsx +41 -0
  29. package/templates/blank/src/main.tsx +12 -0
  30. package/templates/refined/app.json +15 -0
  31. package/templates/refined/src/App.tsx +198 -0
  32. 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
+ }
@@ -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
+ }