@jchat/create-addon 1.0.0-alpha.22 → 1.0.0-alpha.24

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/CHANGELOG.md CHANGED
@@ -1,37 +1,63 @@
1
1
  # @jchat/create-addon
2
2
 
3
+ ## 1.0.0-alpha.24
4
+
5
+ ### Minor Changes
6
+
7
+ - Add addon logo validation, database schema, scaffolding, and UI card rendering
8
+
9
+ ### Patch Changes
10
+
11
+ - Update default service and documentation domains to jchatcloud.com
12
+
13
+ - Update package repository URLs to jarvistack organization
14
+
15
+ - Improve code formatting and style consistency
16
+
17
+ - Refactor add-on scaffolder into modular template providers and orchestrator
18
+
19
+ - Bumped `@jchat/*` dependencies:
20
+ - [`addon-sdk@1.0.0-alpha.24`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.24)
21
+
22
+ ## 1.0.0-alpha.23
23
+
24
+ ### Patch Changes
25
+
26
+ - Bumped `@jchat/*` dependencies:
27
+ - [`addon-sdk@1.0.0-alpha.23`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.23)
28
+
3
29
  ## 1.0.0-alpha.22
4
30
 
5
31
  ### Patch Changes
6
32
 
7
33
  - Update addon scaffolding templates to snake_case database conventions
8
-
34
+
9
35
  - Update default database migration templates to snake_case naming conventions
10
36
  - Update default service and documentation domains to jchatplatform.com
11
37
 
12
38
  - Bumped `@jchat/*` dependencies:
13
- - [`addon-sdk@1.0.0-alpha.22`](https://github.com/mjjabarullah/jchat/releases/tag/addon-sdk@v1.0.0-alpha.22)
39
+ - [`addon-sdk@1.0.0-alpha.22`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.22)
14
40
 
15
41
  ## 1.0.0-alpha.21
16
42
 
17
43
  ### Patch Changes
18
44
 
19
45
  - Bumped `@jchat/*` dependencies:
20
- - [`addon-sdk@1.0.0-alpha.21`](https://github.com/mjjabarullah/jchat/releases/tag/addon-sdk@v1.0.0-alpha.21)
46
+ - [`addon-sdk@1.0.0-alpha.21`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.21)
21
47
 
22
48
  ## 1.0.0-alpha.20
23
49
 
24
50
  ### Patch Changes
25
51
 
26
52
  - Bumped `@jchat/*` dependencies:
27
- - [`addon-sdk@1.0.0-alpha.20`](https://github.com/mjjabarullah/jchat/releases/tag/addon-sdk@v1.0.0-alpha.20)
53
+ - [`addon-sdk@1.0.0-alpha.20`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.20)
28
54
 
29
55
  ## 1.0.0-alpha.19
30
56
 
31
57
  ### Patch Changes
32
58
 
33
59
  - Bumped `@jchat/*` dependencies:
34
- - [`addon-sdk@1.0.0-alpha.19`](https://github.com/mjjabarullah/jchat/releases/tag/addon-sdk@v1.0.0-alpha.19)
60
+ - [`addon-sdk@1.0.0-alpha.19`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.19)
35
61
 
36
62
  ## 1.0.0-alpha.17
37
63
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @jchat/create-addon
2
2
 
3
- Official CLI scaffolding tool for generating self-contained [JChat](https://jchatplatform.com) addon development workspaces and interactive sandbox environments.
3
+ Official CLI scaffolding tool for generating self-contained [JChat](https://jchatcloud.com) addon development workspaces and interactive sandbox environments.
4
4
 
5
5
  ---
6
6
 
@@ -149,16 +149,16 @@ my-addon/
149
149
 
150
150
  ## CLI Flags & Options
151
151
 
152
- | Option | Description | Default |
153
- | :----------------------- | :----------------------------------------------------------------------------------------- | :----------------------------------- |
154
- | `<addon-id>` | Addon identifier (lowercase letters, numbers, hyphens). Prompted interactively if omitted. | — |
155
- | `--target=<dir>` | Output directory for the scaffolded project. | `./<addon-id>` |
156
- | `--template=<type>` | Addon template type: `fullstack` (UI + API + DB) or `ui` (Frontend only). | `fullstack` |
157
- | `--mount-points=<p1,p2>` | Comma-separated list of UI mount points (see below). | `chat:toolbar,chat:plus-menu` |
158
- | `--name=<displayName>` | Human-readable display name for the addon (e.g. `--name="Poll Manager"`). | Auto-derived from `<addon-id>` |
159
- | `--workspace` | Target monorepo workspace mode (scaffolds to `addons/<addon-id>`). | `false` |
160
- | `--image=<image>` | Custom container image for the JChat sandbox runtime. | `ghcr.io/mjjabarullah/jchat-sandbox` |
161
- | `--help`, `-h` | Display CLI usage and options. | — |
152
+ | Option | Description | Default |
153
+ | :----------------------- | :----------------------------------------------------------------------------------------- | :--------------------------------- |
154
+ | `<addon-id>` | Addon identifier (lowercase letters, numbers, hyphens). Prompted interactively if omitted. | — |
155
+ | `--target=<dir>` | Output directory for the scaffolded project. | `./<addon-id>` |
156
+ | `--template=<type>` | Addon template type: `fullstack` (UI + API + DB) or `ui` (Frontend only). | `fullstack` |
157
+ | `--mount-points=<p1,p2>` | Comma-separated list of UI mount points (see below). | `chat:toolbar,chat:plus-menu` |
158
+ | `--name=<displayName>` | Human-readable display name for the addon (e.g. `--name="Poll Manager"`). | Auto-derived from `<addon-id>` |
159
+ | `--workspace` | Target monorepo workspace mode (scaffolds to `addons/<addon-id>`). | `false` |
160
+ | `--image=<image>` | Custom container image for the JChat sandbox runtime. | `ghcr.io/jchatcloud/jchat-sandbox` |
161
+ | `--help`, `-h` | Display CLI usage and options. | — |
162
162
 
163
163
  ---
164
164
 
package/dist/cli.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as MountPoint } from "./contracts.mjs";
1
+ import { r as MountPoint } from "./contracts2.mjs";
2
2
  import { t as AddonTemplateType } from "./generator.mjs";
3
3
  //#region src/cli.d.ts
4
4
  export interface CreatorArguments {
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- import{t as e}from"./contracts.d.mts";import{a as t,i as n,o as r}from"./generator.mjs";import*as i from"node:fs";import*as a from"node:path";import{styleText as o}from"node:util";import s,{stdin as c,stdout as l}from"node:process";import*as u from"node:readline";import d from"node:readline";import{ReadStream as f}from"node:tty";var p=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);const m=(()=>{let e=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return t=>{let n=0;for(e.lastIndex=0;e.test(t);)n+=1;return t.length-n}})(),h=e=>e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510,g=e=>e===8987||e===9001||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e>=131072&&e<=196605||e>=196608&&e<=262141,_=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,v=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,y=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy,b=/\t{1,1000}/y,x=/[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy,S=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,ee=/\p{M}+/gu,te={limit:1/0,ellipsis:``},C=(e,t={},n={})=>{let r=t.limit??1/0,i=t.ellipsis??``,a=t?.ellipsisWidth??(i?C(i,te,n).width:0),o=n.controlWidth??0,s=n.tabWidth??8,c=n.emojiWidth??2,l=n.regularWidth??1,u=n.wideWidth??2,d=[[S,l],[_,0],[v,o],[b,s],[x,c],[y,u]],f=0,p=0,w=e.length,T=0,E=!1,D=w,O=Math.max(0,r-a),k=0,A=0,j=0,M=0;outer:for(;;){if(A>k||p>=w&&p>f){let t=e.slice(k,A)||e.slice(f,p);T=0;for(let e of t.replaceAll(ee,``)){let t=e.codePointAt(0)||0;if(M=h(t)?2:g(t)?u:l,j+M>O&&(D=Math.min(D,Math.max(k,f)+T)),j+M>r){E=!0;break outer}T+=e.length,j+=M}k=A=0}if(p>=w)break outer;for(let t=0,n=d.length;t<n;t++){let[n,i]=d[t];if(n.lastIndex=p,n.test(e)){if(T=n===y?m(e.slice(p,n.lastIndex)):n===x?1:n.lastIndex-p,M=T*i,j+M>O&&(D=Math.min(D,p+Math.floor((O-j)/i))),j+M>r){E=!0;break outer}j+=M,k=f,A=p,p=f=n.lastIndex;continue outer}}p+=1}return{width:E?O:j,index:E?D:w,truncated:E,ellipsed:E&&r>=a}},w={limit:1/0,ellipsis:``,ellipsisWidth:0},T=(e,t={})=>C(e,w,t).width,E=`]8;;`,D=RegExp(`(?:\\[(?<code>\\d+)m|\\${E}(?<uri>.*))`,`y`),O=e=>{if(e>=30&&e<=37||e>=90&&e<=97)return 39;if(e>=40&&e<=47||e>=100&&e<=107)return 49;if(e===1||e===2)return 22;if(e===3)return 23;if(e===4)return 24;if(e===7)return 27;if(e===8)return 28;if(e===9)return 29;if(e===0)return 0},k=e=>`[${e}m`,A=e=>`${E}${e}`,j=(e,t,n)=>{let r=t[Symbol.iterator](),i=!1,a=!1,o=e.at(-1),s=o===void 0?0:T(o),c=r.next(),l=r.next(),u=0;for(;!c.done;){let o=c.value,d=T(o);s+d<=n?e[e.length-1]+=o:(e.push(o),s=0),(o===`\x1B`||o===`›`)&&(i=!0,a=t.startsWith(E,u+1)),i?a?o===`\x07`&&(i=!1,a=!1):o===`m`&&(i=!1):(s+=d,s===n&&!l.done&&(e.push(``),s=0)),c=l,l=r.next(),u+=o.length}o=e.at(-1),!s&&o!==void 0&&o.length&&e.length>1&&(e[e.length-2]+=e.pop())},M=e=>{let t=e.split(` `),n=t.length;for(;n&&!T(t[n-1]);)n--;return n===t.length?e:t.slice(0,n).join(` `)+t.slice(n).join(``)},ne=(e,t,n={})=>{if(n.trim!==!1&&e.trim()===``)return``;let r=``,i,a,o=e.split(` `),s=[``],c=0;for(let e=0;e<o.length;e++){let r=o[e];if(n.trim!==!1){let e=s.at(-1)??``,t=e.trimStart();e.length!==t.length&&(s[s.length-1]=t,c=T(t))}e!==0&&(c>=t&&(n.wordWrap===!1||n.trim===!1)&&(s.push(``),c=0),(c||n.trim===!1)&&(s[s.length-1]+=` `,c++));let i=T(r);if(n.hard&&i>t){let e=t-c,n=1+Math.floor((i-e-1)/t);Math.floor((i-1)/t)<n&&s.push(``),j(s,r,t),c=T(s.at(-1)??``);continue}if(c+i>t&&c&&i){if(n.wordWrap===!1&&c<t){j(s,r,t),c=T(s.at(-1)??``);continue}s.push(``),c=0}if(c+i>t&&n.wordWrap===!1){j(s,r,t),c=T(s.at(-1)??``);continue}s[s.length-1]+=r,c+=i}n.trim!==!1&&(s=s.map(e=>M(e)));let l=s.join(`
2
+ import{n as e}from"./contracts2.d.mts";import{a as t,i as n,r}from"./generator.mjs";import*as i from"node:fs";import*as a from"node:path";import{styleText as o}from"node:util";import s,{stdin as c,stdout as l}from"node:process";import*as u from"node:readline";import d from"node:readline";import{ReadStream as f}from"node:tty";var p=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);const m=(()=>{let e=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return t=>{let n=0;for(e.lastIndex=0;e.test(t);)n+=1;return t.length-n}})(),h=e=>e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510,g=e=>e===8987||e===9001||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e>=131072&&e<=196605||e>=196608&&e<=262141,_=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,v=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,y=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy,b=/\t{1,1000}/y,x=/[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy,S=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,ee=/\p{M}+/gu,te={limit:1/0,ellipsis:``},C=(e,t={},n={})=>{let r=t.limit??1/0,i=t.ellipsis??``,a=t?.ellipsisWidth??(i?C(i,te,n).width:0),o=n.controlWidth??0,s=n.tabWidth??8,c=n.emojiWidth??2,l=n.regularWidth??1,u=n.wideWidth??2,d=[[S,l],[_,0],[v,o],[b,s],[x,c],[y,u]],f=0,p=0,w=e.length,T=0,E=!1,D=w,O=Math.max(0,r-a),k=0,A=0,j=0,M=0;outer:for(;;){if(A>k||p>=w&&p>f){let t=e.slice(k,A)||e.slice(f,p);T=0;for(let e of t.replaceAll(ee,``)){let t=e.codePointAt(0)||0;if(M=h(t)?2:g(t)?u:l,j+M>O&&(D=Math.min(D,Math.max(k,f)+T)),j+M>r){E=!0;break outer}T+=e.length,j+=M}k=A=0}if(p>=w)break outer;for(let t=0,n=d.length;t<n;t++){let[n,i]=d[t];if(n.lastIndex=p,n.test(e)){if(T=n===y?m(e.slice(p,n.lastIndex)):n===x?1:n.lastIndex-p,M=T*i,j+M>O&&(D=Math.min(D,p+Math.floor((O-j)/i))),j+M>r){E=!0;break outer}j+=M,k=f,A=p,p=f=n.lastIndex;continue outer}}p+=1}return{width:E?O:j,index:E?D:w,truncated:E,ellipsed:E&&r>=a}},w={limit:1/0,ellipsis:``,ellipsisWidth:0},T=(e,t={})=>C(e,w,t).width,E=`]8;;`,D=RegExp(`(?:\\[(?<code>\\d+)m|\\${E}(?<uri>.*))`,`y`),O=e=>{if(e>=30&&e<=37||e>=90&&e<=97)return 39;if(e>=40&&e<=47||e>=100&&e<=107)return 49;if(e===1||e===2)return 22;if(e===3)return 23;if(e===4)return 24;if(e===7)return 27;if(e===8)return 28;if(e===9)return 29;if(e===0)return 0},k=e=>`[${e}m`,A=e=>`${E}${e}`,j=(e,t,n)=>{let r=t[Symbol.iterator](),i=!1,a=!1,o=e.at(-1),s=o===void 0?0:T(o),c=r.next(),l=r.next(),u=0;for(;!c.done;){let o=c.value,d=T(o);s+d<=n?e[e.length-1]+=o:(e.push(o),s=0),(o===`\x1B`||o===`›`)&&(i=!0,a=t.startsWith(E,u+1)),i?a?o===`\x07`&&(i=!1,a=!1):o===`m`&&(i=!1):(s+=d,s===n&&!l.done&&(e.push(``),s=0)),c=l,l=r.next(),u+=o.length}o=e.at(-1),!s&&o!==void 0&&o.length&&e.length>1&&(e[e.length-2]+=e.pop())},M=e=>{let t=e.split(` `),n=t.length;for(;n&&!T(t[n-1]);)n--;return n===t.length?e:t.slice(0,n).join(` `)+t.slice(n).join(``)},ne=(e,t,n={})=>{if(n.trim!==!1&&e.trim()===``)return``;let r=``,i,a,o=e.split(` `),s=[``],c=0;for(let e=0;e<o.length;e++){let r=o[e];if(n.trim!==!1){let e=s.at(-1)??``,t=e.trimStart();e.length!==t.length&&(s[s.length-1]=t,c=T(t))}e!==0&&(c>=t&&(n.wordWrap===!1||n.trim===!1)&&(s.push(``),c=0),(c||n.trim===!1)&&(s[s.length-1]+=` `,c++));let i=T(r);if(n.hard&&i>t){let e=t-c,n=1+Math.floor((i-e-1)/t);Math.floor((i-1)/t)<n&&s.push(``),j(s,r,t),c=T(s.at(-1)??``);continue}if(c+i>t&&c&&i){if(n.wordWrap===!1&&c<t){j(s,r,t),c=T(s.at(-1)??``);continue}s.push(``),c=0}if(c+i>t&&n.wordWrap===!1){j(s,r,t),c=T(s.at(-1)??``);continue}s[s.length-1]+=r,c+=i}n.trim!==!1&&(s=s.map(e=>M(e)));let l=s.join(`
3
3
  `),u=!1;for(let e=0;e<l.length;e++){let t=l[e];if(r+=t,u)u=!1;else if(u=t>=`\ud800`&&t<=`\udbff`,u)continue;if(t===`\x1B`||t===`›`){D.lastIndex=e+1;let t=D.exec(l)?.groups;if(t?.code!==void 0){let e=Number.parseFloat(t.code);i=e===39?void 0:e}else t?.uri!==void 0&&(a=t.uri.length===0?void 0:t.uri)}if(l[e+1]===`
4
4
  `){a&&(r+=A(``));let e=i?O(i):void 0;i&&e&&(r+=k(e))}else t===`
5
5
  `&&(i&&O(i)&&(r+=k(i)),a&&(r+=A(a)))}return r},re=/\r?\n/;function N(e,t,n){return String(e).normalize().split(re).map(e=>ne(e,t,n)).join(`
@@ -63,9 +63,9 @@ ${a}${e}
63
63
  `}case`submit`:{let e=a?`${t?` `:``}${o(`dim`,a)}`:``;return`${n}${t?o(`gray`,K):``}${e}`}case`cancel`:{let e=a?` ${o([`strikethrough`,`dim`],a)}`:``,r=t?o(`gray`,K):``;return`${n}${r}${e}${a.trim()?`
64
64
  ${r}`:``}`}default:return`${n}${t?`${o(`cyan`,K)} `:``}${i}
65
65
  ${t?o(`cyan`,q):``}
66
- `}}}).prompt();function Ie(e){let t=e.find(e=>!e.startsWith(`--`));if(t===void 0||t.startsWith(`-`))throw Error(`Usage: bunx @jchat/create-addon <addon-id> [--target=<directory>] [--image=<image>] [--workspace] [--template=ui|fullstack] [--mount-points=p1,p2] [--name=<displayName>]`);let n=e.find(e=>e.startsWith(`--target=`)),r=e.find(e=>e.startsWith(`--image=`)),i=e.find(e=>e.startsWith(`--template=`)),o=e.find(e=>e.startsWith(`--mount-points=`)||e.startsWith(`--mountPoints=`)),s=e.find(e=>e.startsWith(`--name=`)),c=e.includes(`--workspace`),l=c?a.join(`addons`,t):t,u=i?i.split(`=`)[1]:void 0,d=o?o.split(`=`)[1]?.split(`,`).filter(Boolean):void 0,f=s?s.slice(7):void 0;return{addonId:t,targetDir:n?.slice(9)||l,sandboxImage:r?.slice(8)||void 0,workspace:c,...u===void 0?{}:{template:u},...d===void 0?{}:{mountPoints:d},...f===void 0?{}:{displayName:f}}}function Le(){try{let e=process.cwd();for(let t=0;t<6;t++){let t=a.join(e,`package.json`);if(i.existsSync(t)){let e=i.readFileSync(t,`utf8`),n=JSON.parse(e);if(n.name===`jchat`&&Array.isArray(n.workspaces))return!0}let n=a.dirname(e);if(n===e)break;e=n}}catch{}return!1}async function Re(t){Ae(`@jchat/create-addon`);let r=t?.trim();if(!r||!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(r)){let e=await $({message:`What is your addon ID?`,placeholder:`my-custom-addon`,initialValue:t,validate(e){if(!e||e.trim().length===0)return`Addon ID is required`;if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(e.trim()))return`Addon ID must contain lowercase letters, numbers, and hyphens (e.g. my-custom-addon)`}});z(e)&&(Z(`Scaffolding cancelled.`),process.exit(0)),r=String(e).trim()}let i=await $({message:`What is the display name?`,initialValue:n(r),validate(e){if(!e||e.trim().length===0)return`Display name is required`}});z(i)&&(Z(`Scaffolding cancelled.`),process.exit(0));let o=await Fe({message:`Choose an addon template:`,options:[{value:`fullstack`,label:`Full-Stack (UI + Backend API + Database)`,hint:`Recommended - includes Elysia routes, Kysely DB, migrations, permissions`},{value:`ui`,label:`Frontend Only (UI Component + Locales)`,hint:`Lightweight client-only extension`}],initialValue:`fullstack`});z(o)&&(Z(`Scaffolding cancelled.`),process.exit(0));let s=await ke({message:`Where should the addon be mounted?`,options:[{value:e.CHAT_TOOLBAR,label:`Chat Toolbar`,hint:`Top header/toolbar in chat`},{value:e.CHAT_PLUS_MENU,label:`Plus Menu (+)`,hint:`Message composer action menu`},{value:e.CHAT_SIDEBAR,label:`Chat Sidebar`,hint:`Right-hand sidebar widget`},{value:e.ADDON_SETTINGS,label:`Addon Settings`,hint:`Site admin dashboard panel`},{value:e.OWNER_SETTINGS,label:`Owner Settings`,hint:`Owner dashboard panel`},{value:e.EMOJI_PICKER_GIF_TAB,label:`GIF Tab`,hint:`Emoji/GIF picker panel tab`},{value:e.EMOJI_PICKER_STICKER_TAB,label:`Sticker Tab`,hint:`Emoji/Sticker picker panel tab`}],initialValues:[e.CHAT_TOOLBAR,e.CHAT_PLUS_MENU],required:!0});z(s)&&(Z(`Scaffolding cancelled.`),process.exit(0));let c=Le(),l=await Fe({message:`Target environment:`,options:c?[{value:`workspace`,label:`JChat Monorepo Workspace (addons/<id>)`,hint:`Detected JChat root`},{value:`standalone`,label:`Standalone DevKit (Docker Sandbox)`,hint:`Independent repository`}]:[{value:`standalone`,label:`Standalone DevKit (Docker Sandbox)`,hint:`Independent repository`},{value:`workspace`,label:`Monorepo Workspace (addons/<id>)`,hint:`Inside existing monorepo`}],initialValue:c?`workspace`:`standalone`});z(l)&&(Z(`Scaffolding cancelled.`),process.exit(0));let u=l===`workspace`,d=u?a.join(`addons`,r):r,f=await $({message:`Target directory:`,initialValue:d,validate(e){if(!e||e.trim().length===0)return`Target directory is required`}});return z(f)&&(Z(`Scaffolding cancelled.`),process.exit(0)),{addonId:r,targetDir:String(f).trim(),displayName:String(i).trim(),template:o,mountPoints:s,workspace:u}}async function ze(e){let n=await Bun.file(new URL(`../package.json`,import.meta.url)).json();if(e.includes(`--help`)||e.includes(`-h`))return console.log(`Usage: bunx @jchat/create-addon [addon-id] [--target=<directory>] [--image=<image>] [--workspace] [--template=ui|fullstack] [--mount-points=p1,p2] [--name=<displayName>]`),``;let i=!e.some(e=>e.startsWith(`-`))&&!(!process.stdin.isTTY||process.env.CI),o=e.find(e=>!e.startsWith(`-`)),s=i?await Re(o):Ie(e),c=i?Ne():void 0;c?.start(`Scaffolding ${s.displayName??s.addonId}...`);let l=``;return s.workspace?(await t({addonId:s.addonId,targetDir:s.targetDir,isMonorepoWorkspace:!0,jchatVersion:n.version,addonSdkVersion:n.version,template:s.template,mountPoints:s.mountPoints,displayName:s.displayName}),l=a.resolve(s.targetDir),c?.stop(`Addon created successfully at ${l}`),i&&je(`Next steps:
66
+ `}}}).prompt();function Ie(e){let t=e.find(e=>!e.startsWith(`--`));if(t===void 0||t.startsWith(`-`))throw Error(`Usage: bunx @jchat/create-addon <addon-id> [--target=<directory>] [--image=<image>] [--workspace] [--template=ui|fullstack] [--mount-points=p1,p2] [--name=<displayName>]`);let n=e.find(e=>e.startsWith(`--target=`)),r=e.find(e=>e.startsWith(`--image=`)),i=e.find(e=>e.startsWith(`--template=`)),o=e.find(e=>e.startsWith(`--mount-points=`)||e.startsWith(`--mountPoints=`)),s=e.find(e=>e.startsWith(`--name=`)),c=e.includes(`--workspace`),l=c?a.join(`addons`,t):t,u=i?i.split(`=`)[1]:void 0,d=o?o.split(`=`)[1]?.split(`,`).filter(Boolean):void 0,f=s?s.slice(7):void 0;return{addonId:t,targetDir:n?.slice(9)||l,sandboxImage:r?.slice(8)||void 0,workspace:c,...u===void 0?{}:{template:u},...d===void 0?{}:{mountPoints:d},...f===void 0?{}:{displayName:f}}}function Le(){try{let e=process.cwd();for(let t=0;t<6;t++){let t=a.join(e,`package.json`);if(i.existsSync(t)){let e=i.readFileSync(t,`utf8`),n=JSON.parse(e);if(n.name===`jchat`&&Array.isArray(n.workspaces))return!0}let n=a.dirname(e);if(n===e)break;e=n}}catch{}return!1}async function Re(t){Ae(`@jchat/create-addon`);let n=t?.trim();if(!n||!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(n)){let e=await $({message:`What is your addon ID?`,placeholder:`my-custom-addon`,initialValue:t,validate(e){if(!e||e.trim().length===0)return`Addon ID is required`;if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(e.trim()))return`Addon ID must contain lowercase letters, numbers, and hyphens (e.g. my-custom-addon)`}});z(e)&&(Z(`Scaffolding cancelled.`),process.exit(0)),n=String(e).trim()}let i=await $({message:`What is the display name?`,initialValue:r(n),validate(e){if(!e||e.trim().length===0)return`Display name is required`}});z(i)&&(Z(`Scaffolding cancelled.`),process.exit(0));let o=await Fe({message:`Choose an addon template:`,options:[{value:`fullstack`,label:`Full-Stack (UI + Backend API + Database)`,hint:`Recommended - includes Elysia routes, Kysely DB, migrations, permissions`},{value:`ui`,label:`Frontend Only (UI Component + Locales)`,hint:`Lightweight client-only extension`}],initialValue:`fullstack`});z(o)&&(Z(`Scaffolding cancelled.`),process.exit(0));let s=await ke({message:`Where should the addon be mounted?`,options:[{value:e.CHAT_TOOLBAR,label:`Chat Toolbar`,hint:`Top header/toolbar in chat`},{value:e.CHAT_PLUS_MENU,label:`Plus Menu (+)`,hint:`Message composer action menu`},{value:e.CHAT_SIDEBAR,label:`Chat Sidebar`,hint:`Right-hand sidebar widget`},{value:e.ADDON_SETTINGS,label:`Addon Settings`,hint:`Site admin dashboard panel`},{value:e.OWNER_SETTINGS,label:`Owner Settings`,hint:`Owner dashboard panel`},{value:e.EMOJI_PICKER_GIF_TAB,label:`GIF Tab`,hint:`Emoji/GIF picker panel tab`},{value:e.EMOJI_PICKER_STICKER_TAB,label:`Sticker Tab`,hint:`Emoji/Sticker picker panel tab`}],initialValues:[e.CHAT_TOOLBAR,e.CHAT_PLUS_MENU],required:!0});z(s)&&(Z(`Scaffolding cancelled.`),process.exit(0));let c=Le(),l=await Fe({message:`Target environment:`,options:c?[{value:`workspace`,label:`JChat Monorepo Workspace (addons/<id>)`,hint:`Detected JChat root`},{value:`standalone`,label:`Standalone DevKit (Docker Sandbox)`,hint:`Independent repository`}]:[{value:`standalone`,label:`Standalone DevKit (Docker Sandbox)`,hint:`Independent repository`},{value:`workspace`,label:`Monorepo Workspace (addons/<id>)`,hint:`Inside existing monorepo`}],initialValue:c?`workspace`:`standalone`});z(l)&&(Z(`Scaffolding cancelled.`),process.exit(0));let u=l===`workspace`,d=u?a.join(`addons`,n):n,f=await $({message:`Target directory:`,initialValue:d,validate(e){if(!e||e.trim().length===0)return`Target directory is required`}});return z(f)&&(Z(`Scaffolding cancelled.`),process.exit(0)),{addonId:n,targetDir:String(f).trim(),displayName:String(i).trim(),template:o,mountPoints:s,workspace:u}}async function ze(e){let r=await Bun.file(new URL(`../package.json`,import.meta.url)).json();if(e.includes(`--help`)||e.includes(`-h`))return console.log(`Usage: bunx @jchat/create-addon [addon-id] [--target=<directory>] [--image=<image>] [--workspace] [--template=ui|fullstack] [--mount-points=p1,p2] [--name=<displayName>]`),``;let i=!e.some(e=>e.startsWith(`-`))&&!(!process.stdin.isTTY||process.env.CI),o=e.find(e=>!e.startsWith(`-`)),s=i?await Re(o):Ie(e),c=i?Ne():void 0;c?.start(`Scaffolding ${s.displayName??s.addonId}...`);let l=``;return s.workspace?(await n({addonId:s.addonId,targetDir:s.targetDir,isMonorepoWorkspace:!0,jchatVersion:r.version,addonSdkVersion:r.version,template:s.template,mountPoints:s.mountPoints,displayName:s.displayName}),l=a.resolve(s.targetDir),c?.stop(`Addon created successfully at ${l}`),i&&je(`Next steps:
67
67
  cd ${s.targetDir}
68
- bun run dev`)):(await r({...s,jchatVersion:n.version,addonSdkVersion:n.version,sandboxImage:s.sandboxImage??`${n.jchat?.sandboxImage??`ghcr.io/mjjabarullah/jchat-sandbox`}:${n.version.replaceAll(`+`,`-`)}`,template:s.template,mountPoints:s.mountPoints,displayName:s.displayName}),l=a.resolve(s.targetDir),c?.stop(`Standalone DevKit created successfully at ${l}`),i&&je(`Next steps:
68
+ bun run dev`)):(await t({...s,jchatVersion:r.version,addonSdkVersion:r.version,sandboxImage:s.sandboxImage??`${r.jchat?.sandboxImage??`ghcr.io/jchatcloud/jchat-sandbox`}:${r.version.replaceAll(`+`,`-`)}`,template:s.template,mountPoints:s.mountPoints,displayName:s.displayName}),l=a.resolve(s.targetDir),c?.stop(`Standalone DevKit created successfully at ${l}`),i&&je(`Next steps:
69
69
  cd ${s.targetDir}
70
70
  cp .env.example .env
71
71
  bun install
@@ -1,4 +1,4 @@
1
- //#region ../addon-sdk/dist/contracts.d.mts
1
+ //#region ../addon-sdk/dist/contracts2.d.mts
2
2
  /** Valid locations where an addon can be rendered within the Jchat layout. */
3
3
  declare const MOUNT_POINTS: {
4
4
  /** Top of the main chat column */
@@ -40,5 +40,6 @@ declare const MOUNT_POINTS: {
40
40
  };
41
41
  /** Union type of all valid addon mount points. */
42
42
  type MountPoint = (typeof MOUNT_POINTS)[keyof typeof MOUNT_POINTS];
43
+ declare const HOST_LOCALES: readonly ["ar", "bg", "hr", "de", "el", "en", "es", "fr", "he", "hi", "kn", "ml", "nl", "pt", "ro", "ru", "ta", "te", "tr", "ur"];
43
44
  //#endregion
44
- export { MountPoint as n, MOUNT_POINTS as t };
45
+ export { MOUNT_POINTS as n, MountPoint as r, HOST_LOCALES as t };
@@ -1,4 +1,4 @@
1
- import { n as MountPoint } from "./contracts.mjs";
1
+ import { r as MountPoint } from "./contracts2.mjs";
2
2
  //#region src/generator.d.ts
3
3
  type AddonTemplateType = "ui" | "fullstack";
4
4
  interface StandaloneDevkitOptions {
@@ -21,7 +21,7 @@ interface AddonWorkspaceOptions {
21
21
  mountPoints?: MountPoint[];
22
22
  displayName?: string;
23
23
  }
24
- declare const HOST_LOCALES: readonly ["ar", "bg", "de", "el", "en", "es", "fr", "he", "hi", "hr", "kn", "ml", "nl", "pt", "ro", "ru", "ta", "te", "tr", "ur"];
24
+ declare function toDisplayName(addonId: string): string;
25
25
  declare function createAddonFiles(options: {
26
26
  addonId: string;
27
27
  isMonorepoWorkspace?: boolean;
@@ -34,6 +34,5 @@ declare function createAddonFiles(options: {
34
34
  declare function writeAddonWorkspace(options: AddonWorkspaceOptions): Promise<void>;
35
35
  declare function createStandaloneDevkitFiles(options: StandaloneDevkitOptions): Readonly<Record<string, string>>;
36
36
  declare function writeStandaloneDevkit(options: StandaloneDevkitOptions): Promise<void>;
37
- declare function toDisplayName(addonId: string): string;
38
37
  //#endregion
39
- export { createAddonFiles as a, writeAddonWorkspace as c, StandaloneDevkitOptions as i, writeStandaloneDevkit as l, AddonWorkspaceOptions as n, createStandaloneDevkitFiles as o, HOST_LOCALES as r, toDisplayName as s, AddonTemplateType as t };
38
+ export { createStandaloneDevkitFiles as a, writeStandaloneDevkit as c, createAddonFiles as i, AddonWorkspaceOptions as n, toDisplayName as o, StandaloneDevkitOptions as r, writeAddonWorkspace as s, AddonTemplateType as t };
@@ -1,145 +1,4 @@
1
- import{t as e}from"./contracts.d.mts";import*as t from"node:fs";import*as n from"node:path";var[r]=[8,()=>[],[``]];const i=[`ar`,`bg`,`de`,`el`,`en`,`es`,`fr`,`he`,`hi`,`hr`,`kn`,`ml`,`nl`,`pt`,`ro`,`ru`,`ta`,`te`,`tr`,`ur`],a=/^[a-z0-9]+(?:-[a-z0-9]+)*$/,o={ar:e=>({welcome:`مرحبًا بك في ${e}`,mounted_at:`تم التثبيت في {{mountPoint}}`,test_button:`اختبار الإضافة`,toast_message:`مرحبًا من ${e}`}),bg:e=>({welcome:`Добре дошли в ${e}`,mounted_at:`Монтирано на {{mountPoint}}`,test_button:`Тестване на добавката`,toast_message:`Здравейте от ${e}`}),de:e=>({welcome:`Willkommen bei ${e}`,mounted_at:`Eingebunden an {{mountPoint}}`,test_button:`Addon testen`,toast_message:`Hallo von ${e}`}),el:e=>({welcome:`Καλώς ήρθατε στο ${e}`,mounted_at:`Προσαρτήθηκε στο {{mountPoint}}`,test_button:`Δοκιμή πρόσθετου`,toast_message:`Γεια σας από το ${e}`}),en:e=>({welcome:`Welcome to ${e}`,mounted_at:`Mounted at {{mountPoint}}`,test_button:`Test addon`,toast_message:`Hello from ${e}`}),es:e=>({welcome:`Bienvenido a ${e}`,mounted_at:`Montado en {{mountPoint}}`,test_button:`Probar complemento`,toast_message:`Hola desde ${e}`}),fr:e=>({welcome:`Bienvenue sur ${e}`,mounted_at:`Monté sur {{mountPoint}}`,test_button:`Tester le plugin`,toast_message:`Bonjour de ${e}`}),he:e=>({welcome:`ברוכים הבאים אל ${e}`,mounted_at:`מותקן ב-{{mountPoint}}`,test_button:`בדיקת התוסף`,toast_message:`שלום מאת ${e}`}),hi:e=>({welcome:`${e} में आपका स्वागत है`,mounted_at:`{{mountPoint}} पर माउंट किया गया`,test_button:`ऐडऑन का परीक्षण करें`,toast_message:`${e} की ओर से नमस्कार`}),hr:e=>({welcome:`Dobrodošli u ${e}`,mounted_at:`Ugrađeno na {{mountPoint}}`,test_button:`Testiraj dodatak`,toast_message:`Pozdrav iz ${e}`}),kn:e=>({welcome:`${e} ಗೆ ಸುಸ್ವಾಗತ`,mounted_at:`{{mountPoint}} ನಲ್ಲಿ ಸ್ಥಾಪಿಸಲಾಗಿದೆ`,test_button:`ಆಡ್ಆನ್ ಪರೀಕ್ಷಿಸಿ`,toast_message:`${e} ನಿಂದ ನಮಸ್ಕಾರ`}),ml:e=>({welcome:`${e}-ലേക്ക് സ്വാഗതം`,mounted_at:`{{mountPoint}}-ൽ ഘടിപ്പിച്ചിരിക്കുന്നു`,test_button:`ആഡ്ഓൺ പരിശോധിക്കുക`,toast_message:`${e}-ൽ നിന്നുള്ള ആശംസകൾ`}),nl:e=>({welcome:`Welkom bij ${e}`,mounted_at:`Gemonteerd op {{mountPoint}}`,test_button:`Addon testen`,toast_message:`Hallo vanuit ${e}`}),pt:e=>({welcome:`Bem-vindo ao ${e}`,mounted_at:`Montado em {{mountPoint}}`,test_button:`Testar extensão`,toast_message:`Olá de ${e}`}),ro:e=>({welcome:`Bun venit la ${e}`,mounted_at:`Montat la {{mountPoint}}`,test_button:`Testează extensia`,toast_message:`Bună din ${e}`}),ru:e=>({welcome:`Добро пожаловать в ${e}`,mounted_at:`Подключено в {{mountPoint}}`,test_button:`Проверить дополнение`,toast_message:`Привет от ${e}`}),ta:e=>({welcome:`${e}-க்கு வரவேற்கிறோம்`,mounted_at:`{{mountPoint}}-ல் பொருத்தப்பட்டுள்ளது`,test_button:`செருகுநிரலை சோதிக்கவும்`,toast_message:`${e}-லிருந்து வணக்கம்`}),te:e=>({welcome:`${e}కి స్వాగతం`,mounted_at:`{{mountPoint}} వద్ద మౌంట్ చేయబడింది`,test_button:`యాడ్ఆన్‌ని పరీక్షించండి`,toast_message:`${e} నుండి నమస్కారం`}),tr:e=>({welcome:`${e}'e hoş geldiniz`,mounted_at:`{{mountPoint}} konumuna yerleştirildi`,test_button:`Eklentiyi test et`,toast_message:`${e}'den merhaba`}),ur:e=>({welcome:`${e} میں خوش آمدید`,mounted_at:`{{mountPoint}} پر نصب ہے`,test_button:`ایڈ آن کا تجربہ کریں`,toast_message:`${e} کی طرف سے ہیلو`})};function s(t){if(!a.test(t.addonId))throw Error(`Addon id must contain lowercase letters, numbers, and hyphens`);let n=(t.template??`ui`)===`fullstack`,s=t.displayName?.trim()||A(t.addonId),c=t.mountPoints&&t.mountPoints.length>0?t.mountPoints:[e.CHAT_TOOLBAR,e.CHAT_PLUS_MENU],l={id:t.addonId,name:s,version:`1.0.0`,description:`${s} addon for JChat`,author:`Developer`,compatibility:{jchat:r(t.jchatVersion),addonSdk:r(t.addonSdkVersion)},locales:[...i],defaultLocale:`en`,frontend:{bundle:`./ui.js`,mountPoints:c},...n?{server:{bundle:`./api.ts`,migrations:[`migrations/001_initial.sql`]},permissions:[`addon.${t.addonId}.use`,`addon.${t.addonId}.manage`],permissionDefinitions:[{name:`addon.${t.addonId}.use`,label:`Use ${s}`,description:`Access and use ${s} in chat`},{name:`addon.${t.addonId}.manage`,label:`Manage ${s}`,description:`Configure and moderate ${s} settings`}]}:{permissions:[]}},u=t.isMonorepoWorkspace?m(t.addonId,s):_(t.addonId,t.addonSdkVersion),d=t.isMonorepoWorkspace?h():v(),f={"package.json":`${JSON.stringify(u,null,2)}\n`,"tsconfig.json":`${JSON.stringify(d,null,2)}\n`,"src/manifest.ts":y(l),"src/tailwind.css":S(),"src/locales/index.ts":b(),"src/locales.test.ts":x(),"src/ui.tsx":E(s,c,n),".agents/skills/jchat-addon-development/SKILL.md":O()};for(let e of i){let t=o[e];f[`src/locales/${e}.json`]=`${JSON.stringify(t(s),null,2)}\n`}return n&&(f[`src/db.ts`]=C(),f[`src/api.ts`]=T(t.addonId),f[`migrations/001_initial.sql`]=w(t.addonId)),Object.freeze(f)}async function c(e){let r=n.resolve(e.targetDir);if(t.existsSync(r))throw Error(`Addon target already exists: ${r}`);let i=Object.entries(s(e));for(let[e]of i){let i=n.join(r,...e.split(`/`));t.mkdirSync(n.dirname(i),{recursive:!0})}await Promise.all(i.map(([e,t])=>{let i=n.join(r,...e.split(`/`));return Bun.write(i,t)}))}function l(e){if(!a.test(e.addonId))throw Error(`Addon id must contain lowercase letters, numbers, and hyphens`);let t=e.sandboxImage??`ghcr.io/mjjabarullah/jchat-sandbox:${e.jchatVersion.replace(/\+/g,`-`)}`,n=s({addonId:e.addonId,isMonorepoWorkspace:!1,jchatVersion:e.jchatVersion,addonSdkVersion:e.addonSdkVersion,template:e.template,mountPoints:e.mountPoints,displayName:e.displayName}),r={".env.example":d(e.addonId,t),".gitignore":[`node_modules/`,`addon/node_modules/`,`addon/build/`,`.env`,``].join(`
2
- `),"README.md":k(e.addonId),"docker-compose.yml":f(),"package.json":`${JSON.stringify(p(e.addonId),null,2)}\n`,"scripts/devkit.ts":D(),".agents/skills/jchat-addon-development/SKILL.md":O()};for(let[e,t]of Object.entries(n))r[`addon/${e}`]=t;return Object.freeze(r)}async function u(e){let r=n.resolve(e.targetDir);if(t.existsSync(r))throw Error(`Development kit target already exists: ${r}`);let i=Object.entries(l(e));for(let[e]of i){let i=n.join(r,...e.split(`/`));t.mkdirSync(n.dirname(i),{recursive:!0})}await Promise.all(i.map(([e,t])=>{let i=n.join(r,...e.split(`/`));return Bun.write(i,t)}))}function d(e,t){return[`JCHAT_SANDBOX_IMAGE=${t}`,`JCHAT_SANDBOX_ADDON_ID=${e}`,`JCHAT_SANDBOX_PORT=4317`,`JCHAT_SANDBOX_HTTP_MOCK_PORT=4318`,`JCHAT_SANDBOX_HTTP_MOCK_OFFLINE=false`,`JCHAT_SANDBOX_ADDON_HTTP_MOCK_URL=http://http-mock:4318`,``].join(`
3
- `)}function f(){return`services:
4
- sandbox:
5
- image: \${JCHAT_SANDBOX_IMAGE:?Copy .env.example to .env}
6
- restart: unless-stopped
7
- environment:
8
- NODE_ENV: development
9
- JCHAT_PORT: "4317"
10
- JCHAT_COOKIE_SECRET: addon-sandbox-cookie-secret
11
- JCHAT_DATABASE_URL: postgresql://jchat:jchat@db:5432/jchat
12
- JCHAT_REDIS_DATABASE_URL: redis://redis:6379
13
- JCHAT_STORAGE_TYPE: LOCAL
14
- JCHAT_BOT_NAME: Sandbox Bot
15
- JCHAT_BOT_EMAIL: bot@sandbox.local
16
- JCHAT_DOMAIN: localhost
17
- JCHAT_SITE_URL: http://localhost:\${JCHAT_SANDBOX_PORT:-4317}
18
- JCHAT_ROUTING_MODE: path
19
- JCHAT_ADDON_ENCRYPTION_KEY: addon-sandbox-encryption-key
20
- JCHAT_ADDON_HTTP_MOCK_URL: \${JCHAT_SANDBOX_ADDON_HTTP_MOCK_URL-http://http-mock:4318}
21
- ports:
22
- - "127.0.0.1:\${JCHAT_SANDBOX_PORT:-4317}:4317"
23
- volumes:
24
- - ./addon:/app/addons/\${JCHAT_SANDBOX_ADDON_ID:?Set addon id}:ro
25
- - sandbox_uploads:/app/uploads
26
- depends_on:
27
- db:
28
- condition: service_healthy
29
- redis:
30
- condition: service_healthy
31
- http-mock:
32
- condition: service_healthy
33
-
34
- http-mock:
35
- image: \${JCHAT_SANDBOX_IMAGE:?Copy .env.example to .env}
36
- entrypoint: ["/app/addon-http-mock"]
37
- environment:
38
- JCHAT_SANDBOX_HTTP_MOCK_PORT: "4318"
39
- JCHAT_SANDBOX_HTTP_MOCK_OFFLINE: \${JCHAT_SANDBOX_HTTP_MOCK_OFFLINE:-false}
40
- ports:
41
- - "127.0.0.1:\${JCHAT_SANDBOX_HTTP_MOCK_PORT:-4318}:4318"
42
- healthcheck:
43
- test: ["CMD", "/app/addon-http-mock", "--healthcheck"]
44
- interval: 2s
45
- timeout: 3s
46
- retries: 30
47
-
48
- db:
49
- image: postgres:18-alpine
50
- environment:
51
- POSTGRES_USER: jchat
52
- POSTGRES_PASSWORD: jchat
53
- POSTGRES_DB: jchat
54
- volumes:
55
- - sandbox_postgres:/var/lib/postgresql/data
56
- healthcheck:
57
- test: ["CMD-SHELL", "pg_isready -U jchat"]
58
- interval: 2s
59
- timeout: 3s
60
- retries: 30
61
-
62
- redis:
63
- image: redis:8.0.6-alpine3.21
64
- volumes:
65
- - sandbox_redis:/data
66
- healthcheck:
67
- test: ["CMD", "redis-cli", "ping"]
68
- interval: 2s
69
- timeout: 3s
70
- retries: 30
71
-
72
- volumes:
73
- sandbox_postgres:
74
- sandbox_redis:
75
- sandbox_uploads:
76
- `}function p(e){return{name:`${e}-development-kit`,private:!0,type:`module`,workspaces:[`addon`],scripts:{sandbox:`bun run ./scripts/devkit.ts run`,"sandbox:test":`bun run ./scripts/devkit.ts test`,"sandbox:reset":`bun run ./scripts/devkit.ts reset`,"sandbox:package":`bun run ./scripts/devkit.ts package`,"sandbox:cleanup":`bun run ./scripts/devkit.ts cleanup`},devDependencies:{"@types/bun":`^1.4.0`},engines:{bun:`>=1.4.0`}}}function m(e,t){return{name:`@jchat/${e}`,version:`1.0.0-alpha.0`,private:!0,description:`${t} addon for JChat`,repository:{type:`git`,url:`git+https://github.com/mjjabarullah/jchat.git`,directory:`addons/${e}`},type:`module`,scripts:{dev:`jchat-addon dev`,build:`tsc --noEmit && jchat-addon build`,test:`bun test`,lint:`oxlint .`,format:`oxfmt . --write`,typecheck:`tsc --noEmit`},dependencies:{},devDependencies:{"@tailwindcss/vite":`catalog:`,"@types/bun":`catalog:`,"@types/react":`catalog:`,"@types/react-dom":`catalog:`,elysia:`catalog:`,vite:`catalog:`},peerDependencies:{"@jchat/addon-sdk":`workspace:*`,"@tanstack/react-query":`catalog:`,react:`catalog:`,"react-dom":`catalog:`}}}function h(){return{extends:`@jchat/addon-sdk/tsconfig.json`,include:[`src/**/*`]}}function g(){try{let e=import.meta.dirname;for(let r=0;r<6;r++){let r=n.join(e,`package.json`);if(t.existsSync(r)){let e=t.readFileSync(r,`utf8`),n=JSON.parse(e);if(n.catalog&&typeof n.catalog==`object`)return n.catalog}let i=n.dirname(e);if(i===e)break;e=i}}catch{}return{}}function _(e,t){let n=g();return{name:`@jchat/${e}`,version:`1.0.0`,private:!0,type:`module`,scripts:{dev:`jchat-addon dev`,build:`tsc --noEmit && jchat-addon build`,test:`bun test`,typecheck:`tsc --noEmit`},dependencies:{},devDependencies:{"@tailwindcss/vite":n[`@tailwindcss/vite`]??`^4.3.3`,"@types/bun":n[`@types/bun`]??`^1.4.0`,"@types/react":n[`@types/react`]??`^19.2.18`,"@types/react-dom":n[`@types/react-dom`]??`^19.2.4`,elysia:n.elysia??`^1.4.29`,tailwindcss:n.tailwindcss??`^4.3.3`,vite:n.vite??`^8.2.1`},peerDependencies:{"@jchat/addon-sdk":`^${t}`,"@tanstack/react-query":n[`@tanstack/react-query`]??`^5.101.4`,react:n.react??`^19.2.8`,"react-dom":n[`react-dom`]??`^19.2.8`}}}function v(){return{extends:`@jchat/addon-sdk/tsconfig.json`,include:[`src/**/*.ts`,`src/**/*.tsx`]}}function y(e){return`import type { AddonManifest } from "@jchat/addon-sdk"
77
-
78
- const manifest: AddonManifest = ${JSON.stringify(e,null,2)}
79
-
80
- export default manifest
81
- `}function b(){return`import ar from "./ar.json"
82
- import bg from "./bg.json"
83
- import de from "./de.json"
84
- import el from "./el.json"
85
- import en from "./en.json"
86
- import es from "./es.json"
87
- import fr from "./fr.json"
88
- import he from "./he.json"
89
- import hi from "./hi.json"
90
- import hr from "./hr.json"
91
- import kn from "./kn.json"
92
- import ml from "./ml.json"
93
- import nl from "./nl.json"
94
- import pt from "./pt.json"
95
- import ro from "./ro.json"
96
- import ru from "./ru.json"
97
- import ta from "./ta.json"
98
- import te from "./te.json"
99
- import tr from "./tr.json"
100
- import ur from "./ur.json"
101
-
102
- export type TranslationKey = keyof typeof en
103
-
104
- export const locales = {
105
- ar,
106
- bg,
107
- de,
108
- el,
109
- en,
110
- es,
111
- fr,
112
- he,
113
- hi,
114
- hr,
115
- kn,
116
- ml,
117
- nl,
118
- pt,
119
- ro,
120
- ru,
121
- ta,
122
- te,
123
- tr,
124
- ur
125
- } as const
126
-
127
- export default locales
128
- `}function x(){return`import { describe, expect, test } from "bun:test"
129
- import { validateAddonLocales } from "@jchat/addon-sdk/i18n-validator"
130
- import * as path from "node:path"
131
-
132
- describe("addon locales", () => {
133
- test("maintains key parity across all 20 host languages", () => {
134
- const localesDir = path.join(import.meta.dir, "locales")
135
- const result = validateAddonLocales(localesDir)
136
- if (!result.valid) {
137
- console.error(result.errors.join("\\n"))
138
- }
139
- expect(result.valid).toBe(true)
140
- })
141
- })
142
- `}function S(){return`@import "@jchat/addon-sdk/ui/tailwind.css";`}function C(){return`import type { ColumnType } from "@jchat/addon-sdk"
1
+ import{n as e,t}from"./contracts2.d.mts";import*as n from"node:fs";import*as r from"node:path";var[i]=[8,()=>[],[``]];function a(e){return`import type { ColumnType, Selectable } from "@jchat/addon-sdk"
143
2
 
144
3
  export interface AddonItemTable {
145
4
  id: string
@@ -151,9 +10,11 @@ export interface AddonItemTable {
151
10
  }
152
11
 
153
12
  export interface AddonDatabase {
154
- addon_items: AddonItemTable
13
+ ${`${e.replace(/-/g,`_`)}_items`}: AddonItemTable
155
14
  }
156
- `}function w(e){let t=`${e.replace(/-/g,`_`)}_items`;return`CREATE TABLE IF NOT EXISTS "addons"."${t}" (
15
+
16
+ export type AddonItem = Selectable<AddonItemTable>
17
+ `}function o(e){let t=`${e.replace(/-/g,`_`)}_items`;return`CREATE TABLE IF NOT EXISTS "addons"."${t}" (
157
18
  "id" VARCHAR(36) PRIMARY KEY,
158
19
  "site_id" VARCHAR(36) NOT NULL,
159
20
  "room_id" VARCHAR(36) NOT NULL,
@@ -164,7 +25,7 @@ export interface AddonDatabase {
164
25
 
165
26
  CREATE INDEX IF NOT EXISTS "${`idx_${t}_site_room`}"
166
27
  ON "addons"."${t}" ("site_id", "room_id", "created_at" DESC);
167
- `}function T(e){let t=`${e.replace(/-/g,`_`)}_items`;return`import type { AddonApp, AddonServerContext } from "@jchat/addon-sdk"
28
+ `}function s(e){let t=`${e.replace(/-/g,`_`)}_items`;return`import type { AddonApp, AddonServerContext } from "@jchat/addon-sdk"
168
29
  import type { AddonDatabase } from "./db"
169
30
 
170
31
  export default (
@@ -184,7 +45,7 @@ export default (
184
45
  async ({ query, user }) => {
185
46
  const siteId = user?.siteId ?? ""
186
47
  const roomId = query.roomId ?? ""
187
- const items = await (db as any)
48
+ const items = await db
188
49
  .selectFrom("${t}")
189
50
  .where("siteId", "=", siteId)
190
51
  .where("roomId", "=", roomId)
@@ -214,7 +75,7 @@ export default (
214
75
  const roomId = body.roomId
215
76
  const title = body.title
216
77
 
217
- await (db as any)
78
+ await db
218
79
  .insertInto("${t}")
219
80
  .values({
220
81
  id,
@@ -237,7 +98,7 @@ export default (
237
98
  }
238
99
  )
239
100
  }
240
- `}function E(e,t,n){return n?`import type { AddonProps } from "@jchat/addon-sdk"
101
+ `}function c(e,t,n){return n?`import type { AddonProps } from "@jchat/addon-sdk"
241
102
  import { useAddonMutation, useAddonQuery, useAddonSDK, useTranslation } from "@jchat/addon-sdk"
242
103
  import Icons from "@jchat/addon-sdk/icon"
243
104
  import { useState } from "react"
@@ -392,7 +253,81 @@ export default function Addon({ mountPoint }: AddonProps) {
392
253
  </div>
393
254
  )
394
255
  }
395
- `}function D(){return`import * as fs from "node:fs"
256
+ `}function l(e,t){return[`JCHAT_SANDBOX_IMAGE=${t}`,`JCHAT_SANDBOX_ADDON_ID=${e}`,`JCHAT_SANDBOX_PORT=4317`,`JCHAT_SANDBOX_HTTP_MOCK_PORT=4318`,`JCHAT_SANDBOX_HTTP_MOCK_OFFLINE=false`,`JCHAT_SANDBOX_ADDON_HTTP_MOCK_URL=http://http-mock:4318`,``].join(`
257
+ `)}function u(){return`services:
258
+ sandbox:
259
+ image: \${JCHAT_SANDBOX_IMAGE:?Copy .env.example to .env}
260
+ restart: unless-stopped
261
+ environment:
262
+ NODE_ENV: development
263
+ JCHAT_PORT: "4317"
264
+ JCHAT_COOKIE_SECRET: addon-sandbox-cookie-secret
265
+ JCHAT_DATABASE_URL: postgresql://jchat:jchat@db:5432/jchat
266
+ JCHAT_REDIS_DATABASE_URL: redis://redis:6379
267
+ JCHAT_STORAGE_TYPE: LOCAL
268
+ JCHAT_BOT_NAME: Sandbox Bot
269
+ JCHAT_BOT_EMAIL: bot@sandbox.local
270
+ JCHAT_DOMAIN: localhost
271
+ JCHAT_SITE_URL: http://localhost:\${JCHAT_SANDBOX_PORT:-4317}
272
+ JCHAT_ROUTING_MODE: path
273
+ JCHAT_ADDON_ENCRYPTION_KEY: addon-sandbox-encryption-key
274
+ JCHAT_ADDON_HTTP_MOCK_URL: \${JCHAT_SANDBOX_ADDON_HTTP_MOCK_URL-http://http-mock:4318}
275
+ ports:
276
+ - "127.0.0.1:\${JCHAT_SANDBOX_PORT:-4317}:4317"
277
+ volumes:
278
+ - ./addon:/app/addons/\${JCHAT_SANDBOX_ADDON_ID:?Set addon id}:ro
279
+ - sandbox_uploads:/app/uploads
280
+ depends_on:
281
+ db:
282
+ condition: service_healthy
283
+ redis:
284
+ condition: service_healthy
285
+ http-mock:
286
+ condition: service_healthy
287
+
288
+ http-mock:
289
+ image: \${JCHAT_SANDBOX_IMAGE:?Copy .env.example to .env}
290
+ entrypoint: ["/app/addon-http-mock"]
291
+ environment:
292
+ JCHAT_SANDBOX_HTTP_MOCK_PORT: "4318"
293
+ JCHAT_SANDBOX_HTTP_MOCK_OFFLINE: \${JCHAT_SANDBOX_HTTP_MOCK_OFFLINE:-false}
294
+ ports:
295
+ - "127.0.0.1:\${JCHAT_SANDBOX_HTTP_MOCK_PORT:-4318}:4318"
296
+ healthcheck:
297
+ test: ["CMD", "/app/addon-http-mock", "--healthcheck"]
298
+ interval: 2s
299
+ timeout: 3s
300
+ retries: 30
301
+
302
+ db:
303
+ image: postgres:18-alpine
304
+ environment:
305
+ POSTGRES_USER: jchat
306
+ POSTGRES_PASSWORD: jchat
307
+ POSTGRES_DB: jchat
308
+ volumes:
309
+ - sandbox_postgres:/var/lib/postgresql/data
310
+ healthcheck:
311
+ test: ["CMD-SHELL", "pg_isready -U jchat"]
312
+ interval: 2s
313
+ timeout: 3s
314
+ retries: 30
315
+
316
+ redis:
317
+ image: redis:8.0.6-alpine3.21
318
+ volumes:
319
+ - sandbox_redis:/data
320
+ healthcheck:
321
+ test: ["CMD", "redis-cli", "ping"]
322
+ interval: 2s
323
+ timeout: 3s
324
+ retries: 30
325
+
326
+ volumes:
327
+ sandbox_postgres:
328
+ sandbox_redis:
329
+ sandbox_uploads:
330
+ `}function d(){return`import * as fs from "node:fs"
396
331
  import * as path from "node:path"
397
332
 
398
333
  type Command = "run" | "test" | "reset" | "package" | "cleanup"
@@ -461,7 +396,74 @@ function readEnvironment(file: string): Record<string, string> {
461
396
  })
462
397
  )
463
398
  }
464
- `}function O(){return`---
399
+ `}function f(e,t){return`# ${t} Development Kit
400
+
401
+ This workspace develops \`${e}\` against the license-free JChat developer sandbox without
402
+ including JChat Core source.
403
+
404
+ ## Start
405
+
406
+ \`\`\`powershell
407
+ Copy-Item .env.example .env
408
+ bun install
409
+ bun sandbox
410
+ \`\`\`
411
+
412
+ Open \`http://127.0.0.1:4317\`. The HTTP fixture recorder is available at
413
+ \`http://127.0.0.1:4318/requests\`.
414
+
415
+ ## Commands
416
+
417
+ - \`bun sandbox\`
418
+ - \`bun sandbox:test\`
419
+ - \`bun sandbox:reset\`
420
+ - \`bun sandbox:package\`
421
+ - \`bun sandbox:cleanup\`
422
+
423
+ The referenced JChat packages and sandbox image must be published before this standalone kit can
424
+ install or start outside the JChat repository.
425
+ `}const p={ar:e=>({welcome:`مرحبًا بك في ${e}`,mounted_at:`تم التثبيت في {{mountPoint}}`,test_button:`اختبار الإضافة`,toast_message:`مرحبًا من ${e}`}),bg:e=>({welcome:`Добре дошли в ${e}`,mounted_at:`Монтирано на {{mountPoint}}`,test_button:`Тестване на добавката`,toast_message:`Здравейте от ${e}`}),de:e=>({welcome:`Willkommen bei ${e}`,mounted_at:`Eingebunden an {{mountPoint}}`,test_button:`Addon testen`,toast_message:`Hallo von ${e}`}),el:e=>({welcome:`Καλώς ήρθατε στο ${e}`,mounted_at:`Προσαρτήθηκε στο {{mountPoint}}`,test_button:`Δοκιμή πρόσθετου`,toast_message:`Γεια σας από το ${e}`}),en:e=>({welcome:`Welcome to ${e}`,mounted_at:`Mounted at {{mountPoint}}`,test_button:`Test addon`,toast_message:`Hello from ${e}`}),es:e=>({welcome:`Bienvenido a ${e}`,mounted_at:`Montado en {{mountPoint}}`,test_button:`Probar complemento`,toast_message:`Hola desde ${e}`}),fr:e=>({welcome:`Bienvenue sur ${e}`,mounted_at:`Monté sur {{mountPoint}}`,test_button:`Tester le module`,toast_message:`Bonjour de ${e}`}),he:e=>({welcome:`ברוכים הבאים אל ${e}`,mounted_at:`מותקן ב-{{mountPoint}}`,test_button:`בדוק תוסף`,toast_message:`שלום מ-${e}`}),hi:e=>({welcome:`${e} में आपका स्वागत है`,mounted_at:`{{mountPoint}} पर स्थापित`,test_button:`ऐडऑन का परीक्षण करें`,toast_message:`${e} से नमस्ते`}),hr:e=>({welcome:`Dobrodošli u ${e}`,mounted_at:`Postavljeno na {{mountPoint}}`,test_button:`Testiraj dodatak`,toast_message:`Pozdrav iz ${e}`}),kn:e=>({welcome:`${e} ಗೆ ಸುಸ್ವಾಗತ`,mounted_at:`{{mountPoint}} ನಲ್ಲಿ ಸ್ಥಾಪಿಸಲಾಗಿದೆ`,test_button:`ಆಡ್ಆನ್ ಪರೀಕ್ಷಿಸಿ`,toast_message:`${e} ಇಂದ ನಮಸ್ಕಾರ`}),ml:e=>({welcome:`${e}-ലേക്ക് സ്വാഗതം`,mounted_at:`{{mountPoint}}-ൽ ഘടിപ്പിച്ചു`,test_button:`ആഡ്ഓൺ പരിശോധിക്കുക`,toast_message:`${e}-ൽ നിന്നുള്ള ആശംസകൾ`}),nl:e=>({welcome:`Welkom bij ${e}`,mounted_at:`Gekoppeld op {{mountPoint}}`,test_button:`Addon testen`,toast_message:`Hallo vanuit ${e}`}),pt:e=>({welcome:`Bem-vindo ao ${e}`,mounted_at:`Montado em {{mountPoint}}`,test_button:`Testar extensão`,toast_message:`Olá de ${e}`}),ro:e=>({welcome:`Bun venit la ${e}`,mounted_at:`Montat la {{mountPoint}}`,test_button:`Testează extensia`,toast_message:`Bună din ${e}`}),ru:e=>({welcome:`Добро пожаловать в ${e}`,mounted_at:`Подключено в {{mountPoint}}`,test_button:`Проверить дополнение`,toast_message:`Привет от ${e}`}),ta:e=>({welcome:`${e}-க்கு வரவேற்கிறோம்`,mounted_at:`{{mountPoint}}-ல் பொருத்தப்பட்டுள்ளது`,test_button:`செருகுநிரலை சோதிக்கவும்`,toast_message:`${e}-லிருந்து வணக்கம்`}),te:e=>({welcome:`${e}కి స్వాగతం`,mounted_at:`{{mountPoint}} వద్ద మౌంట్ చేయబడింది`,test_button:`యాడ్ఆన్‌ని పరీక్షించండి`,toast_message:`${e} నుండి నమస్కారం`}),tr:e=>({welcome:`${e}'e hoş geldiniz`,mounted_at:`{{mountPoint}} konumuna yerleştirildi`,test_button:`Eklentiyi test et`,toast_message:`${e}'den merhaba`}),ur:e=>({welcome:`${e} میں خوش آمدید`,mounted_at:`{{mountPoint}} پر نصب ہے`,test_button:`ایڈ آن کا تجربہ کریں`,toast_message:`${e} کی طرف سے ہیلو`})};function m(){return`${t.map(e=>`import ${e} from "./${e}.json"`).join(`
426
+ `)}
427
+
428
+ export type TranslationKey = keyof typeof en
429
+
430
+ export const locales = {
431
+ ${t.map(e=>` ${e}`).join(`,
432
+ `)}
433
+ } as const
434
+
435
+ export default locales
436
+ `}function h(){return`import { describe, expect, test } from "bun:test"
437
+ import { validateAddonLocales } from "@jchat/addon-sdk/i18n-validator"
438
+ import * as path from "node:path"
439
+
440
+ describe("addon locales", () => {
441
+ test("maintains key parity across all 20 host languages", () => {
442
+ const localesDir = path.join(import.meta.dir, "locales")
443
+ const result = validateAddonLocales(localesDir)
444
+ if (!result.valid) {
445
+ console.error(result.errors.join("\\n"))
446
+ }
447
+ expect(result.valid).toBe(true)
448
+ })
449
+ })
450
+ `}function g(e){let n={"src/locales/index.ts":m(),"src/locales.test.ts":h()};for(let r of t){let t=p[r];n[`src/locales/${r}.json`]=`${JSON.stringify(t(e),null,2)}\n`}return n}function _(e){return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128" height="128">
451
+ <defs>
452
+ <linearGradient id="addon-grad" x1="0%" y1="0%" x2="100%" y2="100%">
453
+ <stop offset="0%" stop-color="#6366f1" />
454
+ <stop offset="100%" stop-color="#a855f7" />
455
+ </linearGradient>
456
+ </defs>
457
+ <rect width="128" height="128" rx="28" fill="url(#addon-grad)" />
458
+ <circle cx="64" cy="64" r="42" fill="white" fill-opacity="0.15" />
459
+ <text x="64" y="76" font-family="system-ui, -apple-system, sans-serif" font-size="44" font-weight="800" fill="white" text-anchor="middle" dominant-baseline="middle">${e.charAt(0).toUpperCase()||`A`}</text>
460
+ </svg>
461
+ `}function v(e){return`import type { AddonManifest } from "@jchat/addon-sdk"
462
+
463
+ const manifest: AddonManifest = ${JSON.stringify(e,null,2)}
464
+
465
+ export default manifest
466
+ `}function y(){return`@import "@jchat/addon-sdk/ui/tailwind.css";`}var b={name:`jchat`,version:`0.0.0`,private:!0,author:{name:`Md.Jabarullah`,email:`support@jchatcloud.com`,url:`https://github.com/jchatcloud`},workspaces:[`apps/*`,`!apps/android`,`packages/*`,`addons/*`],scripts:{dev:`bun run --parallel chat:dev addons:dev`,"chat:dev":`bun --watch apps/chat/main.ts`,build:`bun run --filter @jchat/chat build`,start:`bun apps/chat/main.ts`,"db:generate":`bun --env-file=.env --filter="@jchat/db" run db:generate`,"db:migrate":`bun --env-file=.env --filter="@jchat/db" run db:migrate`,"db:seed":`bun --env-file=.env --filter="@jchat/db" run db:seed`,"db:studio":`bun --env-file=.env --filter="@jchat/db" run db:studio`,"db:push":`bun --env-file=.env --filter="@jchat/db" run db:push`,"db:pull":`bun --env-file=.env --filter="@jchat/db" run db:pull`,"icon:build":`bun run --filter @jchat/icon build`,"ui:build":`bun run --filter @jchat/ui build`,"addon-sdk:build":`bun run icon:build && bun run ui:build && bun run --filter @jchat/addon-sdk build`,"create-addon:build":`bun run --filter @jchat/create-addon build`,"create-addon:test":`bun run --filter @jchat/create-addon test`,"create-addon":`bun run ./packages/create-addon/src/cli.ts`,"runtime:build":`bun run --filter @jchat/runtime build`,"addons:dev":`bun --filter='./addons/*' --parallel run dev`,"addons:init":`bun run ./packages/create-addon/src/cli.ts --workspace`,"addons:sync":`bun run ./scripts/sync-local-addons.ts`,"addons:sandbox":`bun run ./scripts/developer-sandbox.ts run`,"addons:sandbox:init":`bun run ./scripts/developer-sandbox.ts init`,"addons:sandbox:test":`bun run ./scripts/developer-sandbox.ts test`,"addons:sandbox:reset":`bun run ./scripts/developer-sandbox.ts reset`,"addons:sandbox:package":`bun run ./scripts/developer-sandbox.ts package`,"addons:sandbox:cleanup":`bun run ./scripts/developer-sandbox.ts cleanup`,"addons:package":`bun run ./scripts/package-addons.ts`,"addon:release":`bun run ./scripts/release-addon.ts`,"addons:devkit:init":`bun run ./scripts/create-addon-development-kit.ts`,"addons:devkit:artifacts:check":`bun run addon-sdk:build && bun run create-addon:build && bun run ./scripts/validate-addon-development-artifacts.ts`,"store:build":`bun run --filter @jchat/store build`,"store:dev":`bun --watch apps/store/main.ts`,"store:db:generate":`bun --filter @jchat/store db:generate`,"store:db:migrate":`bun --env-file=apps/store/.env --filter @jchat/store db:migrate`,"store:db:seed":`bun --env-file=apps/store/.env --filter @jchat/store db:seed`,"store:test":`bun run --filter @jchat/store test`,"store:contracts:test":`bun run --filter @jchat/store-contracts test`,"license:build":`bun run --filter @jchat/license build`,"license:dev":`bun --watch apps/license/src/server.ts`,"license:start":`bun run --filter @jchat/license start`,"license:db:generate":`bun --filter @jchat/license db:generate`,"license:db:push":`bun --filter @jchat/license db:push`,"license:test":`bun --env-file=apps/license/.env.test test apps/license`,prepare:`git config core.hooksPath .githooks && bun run addon-sdk:build && bun run runtime:build`,predev:`bun run addon-sdk:build && bun run runtime:build`,release:`bun run ./scripts/release.ts`,"version:addon-sdk":`bun run ./scripts/set-addon-artifact-version.ts sdk`,"version:create-addon":`bun run ./scripts/set-addon-artifact-version.ts creator`,"check:translations":`bun ./scripts/check-translations.ts`,"audit:changes":`bun ./scripts/audit-changes.ts`,"update:geoip":`bun ./scripts/update-geoip.ts`,test:`bun --filter="@jchat/chat" run test:api`,"test:api":`bun --env-file=.env.test --filter="@jchat/chat" run test:api`,"test:unit":`bun --filter="@jchat/chat" run test:unit`,"test:packages":`bun test packages/`,"test:store":`bun run --filter @jchat/store test`,"test:license":`bun --env-file=apps/license/.env.test test apps/license`,"test:watch":`bun --filter="@jchat/chat" run test:api:watch`,"test:coverage":`bun --filter="@jchat/chat" run test:api:coverage`,"test:e2e":`playwright test`,"test:e2e:ui":`playwright test --ui`,"benchmark:chat":`bun run ./scripts/benchmark-chat.ts`,pretypecheck:`bun run addon-sdk:build && bun run runtime:build`,typecheck:`bun --filter='*' run typecheck`,lint:`bun --filter='*' run lint`,format:`bun --filter='*' run format`,change:`bun run ./scripts/release-engine/cli.ts`,"version-packages":`bun run ./scripts/release-engine/version.ts`,"release-packages":`bun run ./scripts/release-engine/publish.ts`,"sync-changelogs":`bun run ./scripts/release-engine/sync-changelog.ts`},devDependencies:{"@clack/prompts":`catalog:`,"@playwright/test":`^1.63.0`,"@types/bun":`catalog:`,elysia:`catalog:`,oxfmt:`catalog:`,oxlint:`catalog:`,typescript:`catalog:`},engines:{node:`>=22.22.0`},packageManager:`bun@1.4.0`,catalog:{"@clack/prompts":`^1.8.1`,"@daypicker/react":`^10.0.1`,"@elysiajs/cors":`^1.4.1`,"@elysiajs/cron":`^1.4.2`,"@elysiajs/eden":`^1.4.9`,"@elysiajs/static":`^1.4.10`,"@react-router/dev":`^8.4.0`,"@react-router/node":`^8.4.0`,"@react-router/serve":`^8.4.0`,"@tailwindcss/vite":`^4.3.3`,"@tanstack/react-query":`^5.103.1`,"@tanstack/react-virtual":`^3.14.13`,"@types/bun":`^1.4.2`,"@types/nodemailer":`^8.0.2`,"@types/react":`^19.3.0`,"@types/react-dom":`^19.3.0`,cn:`^0.3.0`,"date-fns":`4.4.0`,"drizzle-orm":`^0.45.2`,"drizzle-kit":`^0.31.0`,elysia:`^1.4.30`,"elysia-helmet":`^3.0.0`,"elysia-ip":`^1.1.0`,"elysia-rate-limit":`^4.6.2`,motion:`^13.4.0`,nodemailer:`^10.0.10`,i18next:`^26.4.2`,"i18next-browser-languagedetector":`^8.2.1`,isbot:`^5.2.2`,jotai:`^3.0.0`,kysely:`^0.29.6`,"lucide-react":`1.47.0`,oxfmt:`^0.68.0`,oxlint:`^1.83.0`,react:`^19.3.0`,"react-dom":`^19.3.0`,"react-hook-form":`7.54.2`,"react-hot-toast":`^2.6.1`,"react-i18next":`^17.0.14`,"react-router":`^8.4.0`,"tailwind-scrollbar":`^4.0.2`,tailwindcss:`^4.3.3`,tsdown:`0.23.0`,typescript:`^7.0.2`,vite:`^8.3.0`,zod:`^4.6.5`},trustedDependencies:[`@tailwindcss/oxide`,`esbuild`,`unrs-resolver`]};function x(){return b&&`catalog`in b&&typeof b.catalog==`object`&&b.catalog!==null?b.catalog:{}}function S(e){return{name:`${e}-development-kit`,private:!0,type:`module`,workspaces:[`addon`],scripts:{sandbox:`bun run ./scripts/devkit.ts run`,"sandbox:test":`bun run ./scripts/devkit.ts test`,"sandbox:reset":`bun run ./scripts/devkit.ts reset`,"sandbox:package":`bun run ./scripts/devkit.ts package`,"sandbox:cleanup":`bun run ./scripts/devkit.ts cleanup`},devDependencies:{"@types/bun":`^1.4.0`},engines:{bun:`>=1.4.0`}}}function C(e,t){return{name:`@jchat/${e}`,version:`1.0.0-alpha.0`,private:!0,description:`${t} addon for JChat`,repository:{type:`git`,url:`git+https://github.com/jchatcloud/jchat.git`,directory:`addons/${e}`},type:`module`,scripts:{dev:`jchat-addon dev`,build:`tsc --noEmit && jchat-addon build`,test:`bun test`,lint:`oxlint .`,format:`oxfmt . --write`,typecheck:`tsc --noEmit`},dependencies:{},devDependencies:{"@tailwindcss/vite":`catalog:`,"@types/bun":`catalog:`,"@types/react":`catalog:`,"@types/react-dom":`catalog:`,elysia:`catalog:`,vite:`catalog:`},peerDependencies:{"@jchat/addon-sdk":`workspace:*`,"@tanstack/react-query":`catalog:`,react:`catalog:`,"react-dom":`catalog:`}}}function w(e,t){let n=x();return{name:`@jchat/${e}`,version:`1.0.0`,private:!0,type:`module`,scripts:{dev:`jchat-addon dev`,build:`tsc --noEmit && jchat-addon build`,test:`bun test`,typecheck:`tsc --noEmit`},dependencies:{},devDependencies:{"@tailwindcss/vite":n[`@tailwindcss/vite`]??`^4.3.3`,"@types/bun":n[`@types/bun`]??`^1.4.0`,"@types/react":n[`@types/react`]??`^19.2.18`,"@types/react-dom":n[`@types/react-dom`]??`^19.2.4`,elysia:n.elysia??`^1.4.29`,tailwindcss:n.tailwindcss??`^4.3.3`,vite:n.vite??`^8.2.1`},peerDependencies:{"@jchat/addon-sdk":`^${t}`,"@tanstack/react-query":n[`@tanstack/react-query`]??`^5.101.4`,react:n.react??`^19.2.8`,"react-dom":n[`react-dom`]??`^19.2.8`}}}function T(){return{extends:`@jchat/addon-sdk/tsconfig.json`,include:[`src/**/*`]}}function E(){return{extends:`@jchat/addon-sdk/tsconfig.json`,include:[`src/**/*.ts`,`src/**/*.tsx`]}}function D(){return`---
465
467
  name: jchat-addon-development
466
468
  description: Comprehensive guide for developing JChat addons using @jchat/addon-sdk, including manifests, UI widgets, direct icon imports, Elysia backend, isolated DB schemas, and i18n.
467
469
  ---
@@ -700,30 +702,5 @@ bun run devkit:start
700
702
  # 4. View sandbox logs
701
703
  bun run devkit:logs
702
704
  \`\`\`
703
- `}function k(e){return`# ${A(e)} Development Kit
704
-
705
- This workspace develops \`${e}\` against the license-free JChat developer sandbox without
706
- including JChat Core source.
707
-
708
- ## Start
709
-
710
- \`\`\`powershell
711
- Copy-Item .env.example .env
712
- bun install
713
- bun sandbox
714
- \`\`\`
715
-
716
- Open \`http://127.0.0.1:4317\`. The HTTP fixture recorder is available at
717
- \`http://127.0.0.1:4318/requests\`.
718
-
719
- ## Commands
720
-
721
- - \`bun sandbox\`
722
- - \`bun sandbox:test\`
723
- - \`bun sandbox:reset\`
724
- - \`bun sandbox:package\`
725
- - \`bun sandbox:cleanup\`
726
-
727
- The referenced JChat packages and sandbox image must be published before this standalone kit can
728
- install or start outside the JChat repository.
729
- `}function A(e){return e.split(`-`).map(e=>`${e[0]?.toUpperCase()??``}${e.slice(1)}`).join(` `)}export{c as a,A as i,s as n,u as o,l as r,i as t};
705
+ `}async function O(e,t,i=`Target already exists`){let a=r.resolve(e);if(n.existsSync(a))throw Error(`${i}: ${a}`);let o=Object.entries(t);for(let[e]of o){let t=r.join(a,...e.split(`/`));n.mkdirSync(r.dirname(t),{recursive:!0})}await Promise.all(o.map(([e,t])=>{let n=r.join(a,...e.split(`/`));return Bun.write(n,t)}))}const k=/^[a-z0-9]+(?:-[a-z0-9]+)*$/;function A(e){return e.split(`-`).map(e=>`${e[0]?.toUpperCase()??``}${e.slice(1)}`).join(` `)}function j(n){if(!k.test(n.addonId))throw Error(`Addon id must contain lowercase letters, numbers, and hyphens`);let r=(n.template??`ui`)===`fullstack`,l=n.displayName?.trim()||A(n.addonId),u=n.mountPoints&&n.mountPoints.length>0?n.mountPoints:[e.CHAT_TOOLBAR,e.CHAT_PLUS_MENU],d={id:n.addonId,name:l,version:`1.0.0`,description:`${l} addon for JChat`,logo:`./assets/logo.svg`,author:`Developer`,compatibility:{jchat:i(n.jchatVersion),addonSdk:i(n.addonSdkVersion)},locales:[...t],defaultLocale:`en`,frontend:{bundle:`./ui.js`,mountPoints:u},...r?{server:{bundle:`./api.ts`,migrations:[`migrations/001_initial.sql`]},permissions:[`addon.${n.addonId}.use`,`addon.${n.addonId}.manage`],permissionDefinitions:[{name:`addon.${n.addonId}.use`,label:`Use ${l}`,description:`Access and use ${l} in chat`},{name:`addon.${n.addonId}.manage`,label:`Manage ${l}`,description:`Configure and moderate ${l} settings`}]}:{permissions:[]}},f=n.isMonorepoWorkspace?C(n.addonId,l):w(n.addonId,n.addonSdkVersion),p=n.isMonorepoWorkspace?T():E(),m={"package.json":`${JSON.stringify(f,null,2)}\n`,"tsconfig.json":`${JSON.stringify(p,null,2)}\n`,"assets/logo.svg":_(l),"src/manifest.ts":v(d),"src/tailwind.css":y(),...g(l),"src/ui.tsx":c(l,u,r),".agents/skills/jchat-addon-development/SKILL.md":D()};return r&&(m[`src/db.ts`]=a(n.addonId),m[`src/api.ts`]=s(n.addonId),m[`migrations/001_initial.sql`]=o(n.addonId)),Object.freeze(m)}async function M(e){await O(e.targetDir,j(e),`Addon target already exists`)}function N(e){if(!k.test(e.addonId))throw Error(`Addon id must contain lowercase letters, numbers, and hyphens`);let t=e.sandboxImage??`ghcr.io/jchatcloud/jchat-sandbox:${e.jchatVersion.replace(/\+/g,`-`)}`,n=e.displayName?.trim()||A(e.addonId),r=j({addonId:e.addonId,isMonorepoWorkspace:!1,jchatVersion:e.jchatVersion,addonSdkVersion:e.addonSdkVersion,template:e.template,mountPoints:e.mountPoints,displayName:e.displayName}),i={".env.example":l(e.addonId,t),".gitignore":[`node_modules/`,`addon/node_modules/`,`addon/build/`,`.env`,``].join(`
706
+ `),"README.md":f(e.addonId,n),"docker-compose.yml":u(),"package.json":`${JSON.stringify(S(e.addonId),null,2)}\n`,"scripts/devkit.ts":d(),".agents/skills/jchat-addon-development/SKILL.md":D()};for(let[e,t]of Object.entries(r))i[`addon/${e}`]=t;return Object.freeze(i)}async function P(e){await O(e.targetDir,N(e),`Development kit target already exists`)}export{P as a,M as i,N as n,A as r,j as t};
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { n as MountPoint, t as MOUNT_POINTS } from "./contracts.mjs";
2
- import { a as createAddonFiles, c as writeAddonWorkspace, i as StandaloneDevkitOptions, l as writeStandaloneDevkit, n as AddonWorkspaceOptions, o as createStandaloneDevkitFiles, r as HOST_LOCALES, s as toDisplayName, t as AddonTemplateType } from "./generator.mjs";
1
+ import { n as MOUNT_POINTS, r as MountPoint, t as HOST_LOCALES } from "./contracts2.mjs";
2
+ import { a as createStandaloneDevkitFiles, c as writeStandaloneDevkit, i as createAddonFiles, n as AddonWorkspaceOptions, o as toDisplayName, r as StandaloneDevkitOptions, s as writeAddonWorkspace, t as AddonTemplateType } from "./generator.mjs";
3
3
  export { type AddonTemplateType, type AddonWorkspaceOptions, HOST_LOCALES, MOUNT_POINTS, type MountPoint, type StandaloneDevkitOptions, createAddonFiles, createStandaloneDevkitFiles, toDisplayName, writeAddonWorkspace, writeStandaloneDevkit };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./contracts.d.mts";import{a as t,i as n,n as r,o as i,r as a,t as o}from"./generator.mjs";export{o as HOST_LOCALES,e as MOUNT_POINTS,r as createAddonFiles,a as createStandaloneDevkitFiles,n as toDisplayName,t as writeAddonWorkspace,i as writeStandaloneDevkit};
1
+ import{n as e,t}from"./contracts2.d.mts";import{a as n,i as r,n as i,r as a,t as o}from"./generator.mjs";export{t as HOST_LOCALES,e as MOUNT_POINTS,o as createAddonFiles,i as createStandaloneDevkitFiles,a as toDisplayName,r as writeAddonWorkspace,n as writeStandaloneDevkit};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jchat/create-addon",
3
- "version": "1.0.0-alpha.22",
3
+ "version": "1.0.0-alpha.24",
4
4
  "private": false,
5
5
  "description": "Command line tool for jchat addon creation.",
6
6
  "keywords": [
@@ -15,7 +15,7 @@
15
15
  "license": "SEE LICENSE IN LICENSE",
16
16
  "repository": {
17
17
  "type": "git",
18
- "url": "git+https://github.com/mjjabarullah/jchat.git",
18
+ "url": "git+https://github.com/jchatcloud/jchat.git",
19
19
  "directory": "packages/create-addon"
20
20
  },
21
21
  "bin": {
@@ -66,6 +66,6 @@
66
66
  "bun": ">=1.4.0"
67
67
  },
68
68
  "jchat": {
69
- "sandboxImage": "ghcr.io/mjjabarullah/jchat-sandbox"
69
+ "sandboxImage": "ghcr.io/jchatcloud/jchat-sandbox"
70
70
  }
71
71
  }