bosia 0.6.25 → 0.7.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bosia",
3
- "version": "0.6.25",
3
+ "version": "0.7.1",
4
4
  "type": "module",
5
5
  "description": "A fast, batteries-included fullstack framework — SSR · Svelte 5 Runes · Bun · ElysiaJS. File-based routing inspired by SvelteKit. No Node.js, no Vite, no adapters.",
6
6
  "keywords": [
@@ -4,13 +4,18 @@
4
4
  // `page.url.pathname`. Backed by `router.currentRoute` (`$state` in
5
5
  // router.svelte.ts), so the `$derived` URL re-runs on every nav.
6
6
  //
7
- // No `params` getter on purpose — Bosia already passes `params` as a prop to
8
- // `+page.svelte` / `+layout.svelte` (see App.svelte), mirroring the modern
9
- // SvelteKit `$app/state` direction. Route components should destructure
10
- // `params` from `$props()`, not from here.
7
+ // Bosia passes `params` as a prop to `+page.svelte` / `+layout.svelte` (see
8
+ // App.svelte), mirroring the modern SvelteKit `$app/state` direction. Route
9
+ // components should destructure `params` from `$props()`. `page.params` still
10
+ // exists as a deprecated, working fallback (reactive, backed by
11
+ // `appState.routeParams`) so legacy code keeps running — it will be removed in
12
+ // 1.0.0.
11
13
 
14
+ import { appState } from "./appState.svelte.ts";
12
15
  import { router } from "./router.svelte.ts";
13
16
 
17
+ let paramsWarned = false;
18
+
14
19
  class Page {
15
20
  #url = $derived.by(() => {
16
21
  if (typeof window === "undefined") return new URL("http://localhost/");
@@ -23,6 +28,21 @@ class Page {
23
28
  get pathname() {
24
29
  return this.#url.pathname;
25
30
  }
31
+
32
+ /**
33
+ * @deprecated Read route params from `$props()` instead:
34
+ * `let { params } = $props()` in `+page.svelte` / `+layout.svelte`.
35
+ * `page.params` is a temporary fallback and will be removed in 1.0.0.
36
+ */
37
+ get params() {
38
+ if (process.env.NODE_ENV !== "production" && !paramsWarned) {
39
+ paramsWarned = true;
40
+ console.warn(
41
+ "[bosia] page.params is deprecated — destructure `params` from $props() in your route component. It will be removed in 1.0.0.",
42
+ );
43
+ }
44
+ return appState.routeParams;
45
+ }
26
46
  }
27
47
 
28
48
  export const page = new Page();
@@ -75,6 +75,50 @@ function chainString(el){
75
75
  return stack.concat(leaf).join(" → ");
76
76
  }
77
77
 
78
+ // ─── Structured AI payload helpers (alt+click flow) ──────────────
79
+ function isFrameworkFrame(f){return f.indexOf("node_modules/bosia")>=0}
80
+ function fileOf(frame){var m=/^(.+):\\d+:\\d+$/.exec(frame);return m?m[1]:frame}
81
+ function endsWith(s,suf){return s.length>=suf.length&&s.lastIndexOf(suf)===s.length-suf.length}
82
+ // Outer→leaf chain with framework (node_modules/bosia) frames removed.
83
+ function userFrames(el){
84
+ var leaf=el.getAttribute("data-bosia-loc")||"";
85
+ var all=collectStack(el).concat(leaf?[leaf]:[]);
86
+ var uf=[];
87
+ for(var i=0;i<all.length;i++)if(!isFrameworkFrame(all[i]))uf.push(all[i]);
88
+ return uf;
89
+ }
90
+ // Nearest-to-leaf +page.svelte (preferred) or +layout.svelte frame.
91
+ function findPageFile(frames){
92
+ var layoutHit=null;
93
+ for(var i=frames.length-1;i>=0;i--){
94
+ var f=fileOf(frames[i]);
95
+ if(endsWith(f,"+page.svelte"))return frames[i];
96
+ if(!layoutHit&&endsWith(f,"+layout.svelte"))layoutHit=frames[i];
97
+ }
98
+ return layoutHit;
99
+ }
100
+ // The clicked element's own direct text (not descendants), collapsed + capped.
101
+ function ownText(el){
102
+ var t="";
103
+ for(var i=0;i<el.childNodes.length;i++){var n=el.childNodes[i];if(n.nodeType===3)t+=n.nodeValue||""}
104
+ t=t.replace(/\\s+/g," ").trim();
105
+ if(t.length>80)t=t.slice(0,80)+"…";
106
+ return t;
107
+ }
108
+ function buildContext(el){
109
+ var leaf=el.getAttribute("data-bosia-loc")||"";
110
+ var frames=userFrames(el);
111
+ var pageFile=findPageFile(frames);
112
+ var lines=["[Inspector]"];
113
+ lines.push("url: "+location.href);
114
+ if(pageFile)lines.push("pageFile: "+pageFile);
115
+ if(leaf&&leaf!==pageFile)lines.push("component: "+leaf);
116
+ var text=ownText(el);
117
+ if(text)lines.push('text: "'+text+'"');
118
+ if(frames.length>1)lines.push("tree: "+frames.join(" → "));
119
+ return lines.join("\\n");
120
+ }
121
+
78
122
  function toast(msg,err){
79
123
  var t=document.createElement("div");
80
124
  t.textContent=msg;
@@ -94,7 +138,7 @@ function send(payload,onOk,onErr){
94
138
  function closeForm(){if(form){form.remove();form=null}}
95
139
  function openForm(loc,el){
96
140
  closeForm();
97
- var chain=chainString(el);
141
+ var chain=userFrames(el).join(" → ");
98
142
  var r=el.getBoundingClientRect();
99
143
  form=document.createElement("div");
100
144
  form.style.cssText="position:fixed;left:"+r.left+"px;top:"+(r.bottom+6)+"px;background:#fff;color:#111;border:1px solid #d4d4d8;border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.18);padding:10px;width:340px;z-index:2147483647;font:13px ui-sans-serif,system-ui,sans-serif";
@@ -112,8 +156,7 @@ function openForm(loc,el){
112
156
  var userComment=ta.value.trim();
113
157
  var payload={file:loc.file,line:loc.line,col:loc.col};
114
158
  if(userComment){
115
- var tree=chain.indexOf(" → ")>=0?("Component tree (outer → leaf): "+chain+"\\n\\n"):"";
116
- payload.comment=tree+userComment;
159
+ payload.comment=buildContext(el)+"\\n---\\n"+userComment;
117
160
  }
118
161
  send(payload,function(j){toast(j.mode==="ai"?"sent to AI":"opened "+loc.file+":"+loc.line)});
119
162
  closeForm();
@@ -1,4 +1,4 @@
1
- DATABASE_URL=postgresql://postgres:postgres@localhost:5432/shop
1
+ DATABASE_URL=sqlite://./data/app.db
2
2
 
3
3
  SESSION_SECRET=change-me-in-production
4
4
 
@@ -10,3 +10,6 @@ public/bosia-tw.css
10
10
  # Local env overrides — never commit secrets
11
11
  .env*.local
12
12
  .env
13
+
14
+ # SQLite database artifacts
15
+ data/*.db*
File without changes
@@ -1,4 +1,4 @@
1
- Update .env with your DATABASE_URL (PostgreSQL) and S3_* credentials.
1
+ Update .env with your DATABASE_URL (SQLite file, e.g. sqlite://./data/app.db) and S3_* credentials.
2
2
  Pick a strong SESSION_SECRET.
3
3
 
4
4
  bun run db:generate
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "features": ["auth", "rbac", "file-upload", "shop"],
3
3
  "featureOptions": {
4
- "drizzle.dialect": "postgres",
5
- "auth.dialect": "postgres",
6
- "rbac.dialect": "postgres",
7
- "file-upload.dialect": "postgres",
8
- "shop.dialect": "postgres"
4
+ "drizzle.dialect": "sqlite",
5
+ "auth.dialect": "sqlite",
6
+ "rbac.dialect": "sqlite",
7
+ "file-upload.dialect": "sqlite",
8
+ "shop.dialect": "sqlite"
9
9
  }
10
10
  }