@jchat/create-addon 1.0.0-alpha.23 → 1.0.0-alpha.25

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,44 +1,76 @@
1
1
  # @jchat/create-addon
2
2
 
3
+ ## 1.0.0-alpha.25
4
+
5
+ ### Patch Changes
6
+
7
+ - Update addon sandbox docker compose template
8
+
9
+ - Update package metadata, documentation, and license links
10
+
11
+ - Update sandbox development environment templates
12
+
13
+ - Bumped `@jchat/*` dependencies:
14
+ - [`addon-sdk@1.0.0-alpha.25`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.25)
15
+
16
+ ## 1.0.0-alpha.24
17
+
18
+ ### Minor Changes
19
+
20
+ - Add addon logo validation, database schema, scaffolding, and UI card rendering
21
+
22
+ ### Patch Changes
23
+
24
+ - Update default service and documentation domains to jchatcloud.com
25
+
26
+ - Update package repository URLs to jarvistack organization
27
+
28
+ - Improve code formatting and style consistency
29
+
30
+ - Refactor add-on scaffolder into modular template providers and orchestrator
31
+
32
+ - Bumped `@jchat/*` dependencies:
33
+ - [`addon-sdk@1.0.0-alpha.24`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.24)
34
+
3
35
  ## 1.0.0-alpha.23
4
36
 
5
37
  ### Patch Changes
6
38
 
7
39
  - Bumped `@jchat/*` dependencies:
8
- - [`addon-sdk@1.0.0-alpha.23`](https://github.com/mjjabarullah/jchat/releases/tag/addon-sdk@v1.0.0-alpha.23)
40
+ - [`addon-sdk@1.0.0-alpha.23`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.23)
9
41
 
10
42
  ## 1.0.0-alpha.22
11
43
 
12
44
  ### Patch Changes
13
45
 
14
46
  - Update addon scaffolding templates to snake_case database conventions
15
-
47
+
16
48
  - Update default database migration templates to snake_case naming conventions
17
49
  - Update default service and documentation domains to jchatplatform.com
18
50
 
19
51
  - Bumped `@jchat/*` dependencies:
20
- - [`addon-sdk@1.0.0-alpha.22`](https://github.com/mjjabarullah/jchat/releases/tag/addon-sdk@v1.0.0-alpha.22)
52
+ - [`addon-sdk@1.0.0-alpha.22`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.22)
21
53
 
22
54
  ## 1.0.0-alpha.21
23
55
 
24
56
  ### Patch Changes
25
57
 
26
58
  - Bumped `@jchat/*` dependencies:
27
- - [`addon-sdk@1.0.0-alpha.21`](https://github.com/mjjabarullah/jchat/releases/tag/addon-sdk@v1.0.0-alpha.21)
59
+ - [`addon-sdk@1.0.0-alpha.21`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.21)
28
60
 
29
61
  ## 1.0.0-alpha.20
30
62
 
31
63
  ### Patch Changes
32
64
 
33
65
  - Bumped `@jchat/*` dependencies:
34
- - [`addon-sdk@1.0.0-alpha.20`](https://github.com/mjjabarullah/jchat/releases/tag/addon-sdk@v1.0.0-alpha.20)
66
+ - [`addon-sdk@1.0.0-alpha.20`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.20)
35
67
 
36
68
  ## 1.0.0-alpha.19
37
69
 
38
70
  ### Patch Changes
39
71
 
40
72
  - Bumped `@jchat/*` dependencies:
41
- - [`addon-sdk@1.0.0-alpha.19`](https://github.com/mjjabarullah/jchat/releases/tag/addon-sdk@v1.0.0-alpha.19)
73
+ - [`addon-sdk@1.0.0-alpha.19`](https://github.com/jchatcloud/jchat/releases/tag/addon-sdk@v1.0.0-alpha.19)
42
74
 
43
75
  ## 1.0.0-alpha.17
44
76
 
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  CUSTOM COMMERCIAL END USER LICENSE AGREEMENT (EULA)
2
2
 
3
- Copyright (c) 2026 JChat Project. All rights reserved.
3
+ Copyright (c) 2026 Jchat Cloud. All rights reserved.
4
4
 
5
5
  1. DEFINITIONS
6
6
  "Software" refers to this npm package and its source code.
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
 
@@ -208,4 +208,4 @@ A built-in test (`src/locales.test.ts`) verifies 100% key parity across all lang
208
208
 
209
209
  ## License
210
210
 
211
- Proprietary — All rights reserved. See the [LICENSE](./LICENSE) file for terms and conditions.
211
+ Proprietary — All rights reserved. See the [Commercial EULA & Licensing Terms](https://jchatcloud.com/terms) for full details.
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,78 @@ 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_DOMAIN: localhost
268
+ JCHAT_SITE_URL: http://localhost:\${JCHAT_SANDBOX_PORT:-4317}
269
+ JCHAT_ROUTING_MODE: path
270
+ JCHAT_ADDON_ENCRYPTION_KEY: addon-sandbox-encryption-key
271
+ JCHAT_ADDON_HTTP_MOCK_URL: \${JCHAT_SANDBOX_ADDON_HTTP_MOCK_URL-http://http-mock:4318}
272
+ ports:
273
+ - "127.0.0.1:\${JCHAT_SANDBOX_PORT:-4317}:4317"
274
+ volumes:
275
+ - ./addon:/app/addons/\${JCHAT_SANDBOX_ADDON_ID:?Set addon id}:ro
276
+ - sandbox_uploads:/app/uploads
277
+ depends_on:
278
+ db:
279
+ condition: service_healthy
280
+ redis:
281
+ condition: service_healthy
282
+ http-mock:
283
+ condition: service_healthy
284
+
285
+ http-mock:
286
+ image: \${JCHAT_SANDBOX_IMAGE:?Copy .env.example to .env}
287
+ entrypoint: ["/app/addon-http-mock"]
288
+ environment:
289
+ JCHAT_SANDBOX_HTTP_MOCK_PORT: "4318"
290
+ JCHAT_SANDBOX_HTTP_MOCK_OFFLINE: \${JCHAT_SANDBOX_HTTP_MOCK_OFFLINE:-false}
291
+ ports:
292
+ - "127.0.0.1:\${JCHAT_SANDBOX_HTTP_MOCK_PORT:-4318}:4318"
293
+ healthcheck:
294
+ test: ["CMD", "/app/addon-http-mock", "--healthcheck"]
295
+ interval: 2s
296
+ timeout: 3s
297
+ retries: 30
298
+
299
+ db:
300
+ image: postgres:18-alpine
301
+ environment:
302
+ POSTGRES_USER: jchat
303
+ POSTGRES_PASSWORD: jchat
304
+ POSTGRES_DB: jchat
305
+ volumes:
306
+ - sandbox_postgres:/var/lib/postgresql/data
307
+ healthcheck:
308
+ test: ["CMD-SHELL", "pg_isready -U jchat"]
309
+ interval: 2s
310
+ timeout: 3s
311
+ retries: 30
312
+
313
+ redis:
314
+ image: redis:8.0.6-alpine3.21
315
+ volumes:
316
+ - sandbox_redis:/data
317
+ healthcheck:
318
+ test: ["CMD", "redis-cli", "ping"]
319
+ interval: 2s
320
+ timeout: 3s
321
+ retries: 30
322
+
323
+ volumes:
324
+ sandbox_postgres:
325
+ sandbox_redis:
326
+ sandbox_uploads:
327
+ `}function d(){return`import * as fs from "node:fs"
396
328
  import * as path from "node:path"
397
329
 
398
330
  type Command = "run" | "test" | "reset" | "package" | "cleanup"
@@ -461,7 +393,74 @@ function readEnvironment(file: string): Record<string, string> {
461
393
  })
462
394
  )
463
395
  }
464
- `}function O(){return`---
396
+ `}function f(e,t){return`# ${t} Development Kit
397
+
398
+ This workspace develops \`${e}\` against the license-free JChat developer sandbox without
399
+ including JChat Core source.
400
+
401
+ ## Start
402
+
403
+ \`\`\`powershell
404
+ Copy-Item .env.example .env
405
+ bun install
406
+ bun sandbox
407
+ \`\`\`
408
+
409
+ Open \`http://127.0.0.1:4317\`. The HTTP fixture recorder is available at
410
+ \`http://127.0.0.1:4318/requests\`.
411
+
412
+ ## Commands
413
+
414
+ - \`bun sandbox\`
415
+ - \`bun sandbox:test\`
416
+ - \`bun sandbox:reset\`
417
+ - \`bun sandbox:package\`
418
+ - \`bun sandbox:cleanup\`
419
+
420
+ The referenced JChat packages and sandbox image must be published before this standalone kit can
421
+ install or start outside the JChat repository.
422
+ `}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(`
423
+ `)}
424
+
425
+ export type TranslationKey = keyof typeof en
426
+
427
+ export const locales = {
428
+ ${t.map(e=>` ${e}`).join(`,
429
+ `)}
430
+ } as const
431
+
432
+ export default locales
433
+ `}function h(){return`import { describe, expect, test } from "bun:test"
434
+ import { validateAddonLocales } from "@jchat/addon-sdk/i18n-validator"
435
+ import * as path from "node:path"
436
+
437
+ describe("addon locales", () => {
438
+ test("maintains key parity across all 20 host languages", () => {
439
+ const localesDir = path.join(import.meta.dir, "locales")
440
+ const result = validateAddonLocales(localesDir)
441
+ if (!result.valid) {
442
+ console.error(result.errors.join("\\n"))
443
+ }
444
+ expect(result.valid).toBe(true)
445
+ })
446
+ })
447
+ `}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">
448
+ <defs>
449
+ <linearGradient id="addon-grad" x1="0%" y1="0%" x2="100%" y2="100%">
450
+ <stop offset="0%" stop-color="#6366f1" />
451
+ <stop offset="100%" stop-color="#a855f7" />
452
+ </linearGradient>
453
+ </defs>
454
+ <rect width="128" height="128" rx="28" fill="url(#addon-grad)" />
455
+ <circle cx="64" cy="64" r="42" fill="white" fill-opacity="0.15" />
456
+ <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>
457
+ </svg>
458
+ `}function v(e){return`import type { AddonManifest } from "@jchat/addon-sdk"
459
+
460
+ const manifest: AddonManifest = ${JSON.stringify(e,null,2)}
461
+
462
+ export default manifest
463
+ `}function y(){return`@import "@jchat/addon-sdk/ui/tailwind.css";`}var b={name:`jchat`,version:`0.0.0`,private:!0,author:{name:`Jchat Cloud`,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:{"@better-auth/api-key":`^1.7.6`,"@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`,"better-auth":`^1.7.6`,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
464
  name: jchat-addon-development
466
465
  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
466
  ---
@@ -700,30 +699,5 @@ bun run devkit:start
700
699
  # 4. View sandbox logs
701
700
  bun run devkit:logs
702
701
  \`\`\`
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};
702
+ `}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(`
703
+ `),"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.23",
3
+ "version": "1.0.0-alpha.25",
4
4
  "private": false,
5
5
  "description": "Command line tool for jchat addon creation.",
6
6
  "keywords": [
@@ -9,15 +9,12 @@
9
9
  "cli",
10
10
  "create",
11
11
  "jchat",
12
+ "jchat cloud",
12
13
  "plugin",
13
14
  "scaffold"
14
15
  ],
16
+ "homepage": "https://jchatcloud.com",
15
17
  "license": "SEE LICENSE IN LICENSE",
16
- "repository": {
17
- "type": "git",
18
- "url": "git+https://github.com/mjjabarullah/jchat.git",
19
- "directory": "packages/create-addon"
20
- },
21
18
  "bin": {
22
19
  "create-addon": "./dist/cli.mjs"
23
20
  },
@@ -66,6 +63,6 @@
66
63
  "bun": ">=1.4.0"
67
64
  },
68
65
  "jchat": {
69
- "sandboxImage": "ghcr.io/mjjabarullah/jchat-sandbox"
66
+ "sandboxImage": "ghcr.io/jchatcloud/jchat-sandbox"
70
67
  }
71
68
  }