@jchat/addon-sdk 1.0.0-alpha.3 → 1.0.0-alpha.31

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/dist/vite.mjs CHANGED
@@ -1,11 +1,28 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { execFileSync } from "node:child_process";
4
1
  import crypto from "node:crypto";
2
+ import path from "node:path";
3
+ import fs from "node:fs";
5
4
  //#region src/vite.ts
6
5
  /**
7
- * Vite plugin to configure Jchat addon manifest generation, bundle backend scripts, copy
8
- * migrations, declarative seed data, and zip production build artifacts.
6
+ * Vite plugin for building JChat sandboxed addon extensions.
7
+ *
8
+ * Configures automatic manifest generation (`manifest.json`), bundles server-side API scripts
9
+ * (`src/api.ts`), embeds scoped Tailwind CSS into the frontend bundle, packages database migrations
10
+ * and seed files, copies documentation (`README.md`), signs database-bearing addon manifests, and
11
+ * zips production build artifacts.
12
+ *
13
+ * @example
14
+ * ;```ts
15
+ * import { jchatAddon } from "@jchat/addon-sdk/vite"
16
+ * import manifest from "./src/manifest"
17
+ * import { defineConfig } from "vite"
18
+ *
19
+ * export default defineConfig({
20
+ * plugins: [jchatAddon({ manifest })]
21
+ * })
22
+ * ```
23
+ *
24
+ * @param options - Configuration options for the JChat addon Vite plugin.
25
+ * @returns A Vite {@link Plugin} instance configured for addon compilation.
9
26
  */
10
27
  function jchatAddon(options) {
11
28
  const { manifest: manifestData } = options;
@@ -15,10 +32,44 @@ function jchatAddon(options) {
15
32
  name: "jchat-addon",
16
33
  apply: "build",
17
34
  config(_, env) {
18
- return { define: { "process.env.NODE_ENV": JSON.stringify(env.mode || "production") } };
35
+ const rootDir = process.cwd();
36
+ const uiEntry = path.resolve(rootDir, "src/ui.tsx");
37
+ const hasUi = fs.existsSync(uiEntry);
38
+ return {
39
+ define: {
40
+ global: "window",
41
+ "process.env.NODE_ENV": JSON.stringify(env.mode || "production")
42
+ },
43
+ build: {
44
+ outDir: "build",
45
+ emptyOutDir: true,
46
+ minify: env.mode === "production",
47
+ ...hasUi ? {
48
+ lib: {
49
+ entry: uiEntry,
50
+ name: manifestData.id,
51
+ formats: ["es"],
52
+ fileName: () => "ui.[hash].js"
53
+ },
54
+ rolldownOptions: {
55
+ external: [
56
+ "react",
57
+ "react-dom",
58
+ "react/jsx-runtime",
59
+ "react/jsx-dev-runtime",
60
+ "@tanstack/react-query",
61
+ "@jchat/addon-sdk",
62
+ "@jchat/addon-sdk/state",
63
+ "@jchat/addon-sdk/ui"
64
+ ],
65
+ output: { format: "esm" }
66
+ }
67
+ } : {}
68
+ }
69
+ };
19
70
  },
20
71
  configResolved(config) {
21
- developmentBuild = config.mode === "development";
72
+ developmentBuild = options.development ?? (config.mode === "development" || Bun.env.JCHAT_ADDON_DEV === "true" || Bun.env.NODE_ENV === "development");
22
73
  if (shouldZip === void 0) shouldZip = config.mode === "production";
23
74
  },
24
75
  async writeBundle() {
@@ -30,7 +81,7 @@ function jchatAddon(options) {
30
81
  if (!fs.existsSync(buildDir)) return;
31
82
  const bundleFile = fs.readdirSync(buildDir).find((f) => f.includes("ui") && f.endsWith(".js"));
32
83
  if (!bundleFile) return;
33
- if (options.css !== false) embedCssIntoBundle(buildDir, manifestData.id);
84
+ if (options.css !== false) embedCssIntoBundle(buildDir);
34
85
  let manifest = {
35
86
  ...manifestData,
36
87
  version: pkg.version,
@@ -41,9 +92,13 @@ function jchatAddon(options) {
41
92
  }
42
93
  };
43
94
  const serverSrcPath = path.resolve(rootDir, "src/api.ts");
44
- const hasServer = fs.existsSync(serverSrcPath);
95
+ const hasServer = await Bun.file(serverSrcPath).exists();
45
96
  if (hasServer) {
46
- execFileSync("bun", createAddonServerBuildArguments(serverSrcPath, path.resolve(buildDir, "api.js"), developmentBuild), { stdio: "inherit" });
97
+ Bun.spawnSync(["bun", ...createAddonServerBuildArguments(serverSrcPath, path.resolve(buildDir, "api.js"), developmentBuild)], { stdio: [
98
+ "inherit",
99
+ "inherit",
100
+ "inherit"
101
+ ] });
47
102
  manifest = {
48
103
  ...manifest,
49
104
  server: {
@@ -59,14 +114,17 @@ function jchatAddon(options) {
59
114
  });
60
115
  for (const relativePath of databaseFiles) {
61
116
  if (path.isAbsolute(relativePath) || relativePath.includes("\\") || relativePath.split("/").includes("..")) throw new Error(`Unsafe addon database file path: ${relativePath}`);
62
- const source = path.resolve(rootDir, relativePath);
63
- if (!fs.existsSync(source) || !fs.statSync(source).isFile()) throw new Error(`Missing addon database file: ${relativePath}`);
64
117
  const destination = path.resolve(buildDir, relativePath);
65
118
  fs.mkdirSync(path.dirname(destination), { recursive: true });
66
- fs.copyFileSync(source, destination);
67
119
  }
120
+ await Promise.all(databaseFiles.map(async (relativePath) => {
121
+ const source = path.resolve(rootDir, relativePath);
122
+ if (!await Bun.file(source).exists() || !fs.statSync(source).isFile()) throw new Error(`Missing addon database file: ${relativePath}`);
123
+ const destination = path.resolve(buildDir, relativePath);
124
+ return Bun.write(destination, Bun.file(source));
125
+ }));
68
126
  if (manifest.server?.migrations?.length || manifest.server?.seeds?.length) {
69
- const signingPrivateKey = requireAddonSigningKey(options.signingPrivateKey ?? process.env.JCHAT_ADDON_SIGNING_PRIVATE_KEY, developmentBuild);
127
+ const signingPrivateKey = requireAddonSigningKey(options.signingPrivateKey ?? Bun.env.JCHAT_ADDON_SIGNING_PRIVATE_KEY, developmentBuild);
70
128
  if (signingPrivateKey) {
71
129
  const archivePaths = [
72
130
  "manifest.json",
@@ -75,36 +133,57 @@ function jchatAddon(options) {
75
133
  ...manifest.server?.seeds ?? []
76
134
  ];
77
135
  if (hasServer) archivePaths.push("api.js");
78
- manifest = signAddonManifest(manifest, archivePaths.map((file) => ({
136
+ const resolvedFiles = await Promise.all(archivePaths.map(async (file) => ({
79
137
  path: file,
80
- contents: file === "manifest.json" ? Buffer.from("") : fs.readFileSync(path.resolve(buildDir, file))
81
- })), signingPrivateKey);
138
+ contents: file === "manifest.json" ? Buffer.from("") : Buffer.from(await Bun.file(path.resolve(buildDir, file)).arrayBuffer())
139
+ })));
140
+ manifest = signAddonManifest(manifest, resolvedFiles, signingPrivateKey);
82
141
  }
83
142
  }
143
+ const readmeSource = path.resolve(rootDir, "README.md");
144
+ if (await Bun.file(readmeSource).exists()) await Bun.write(path.resolve(buildDir, "README.md"), Bun.file(readmeSource));
145
+ const vendorLicensesContent = await generateAddonVendorLicenses(rootDir, manifest.name);
146
+ await Bun.write(path.resolve(buildDir, "vendor-licenses.txt"), vendorLicensesContent);
84
147
  const manifestJson = JSON.stringify(manifest, null, 2);
85
- fs.writeFileSync(path.resolve(buildDir, "manifest.json"), manifestJson);
148
+ await Bun.write(path.resolve(buildDir, "manifest.json"), manifestJson);
86
149
  if (shouldZip) {
87
150
  const zipName = `${manifest.id}-${pkg.version}.zip`;
88
151
  const filesToZip = ["manifest.json", bundleFile];
89
- if (fs.existsSync(path.resolve(buildDir, "api.js"))) filesToZip.push("api.js");
152
+ if (await Bun.file(path.resolve(buildDir, "api.js")).exists()) filesToZip.push("api.js");
153
+ if (await Bun.file(path.resolve(buildDir, "README.md")).exists()) filesToZip.push("README.md");
154
+ if (await Bun.file(path.resolve(buildDir, "vendor-licenses.txt")).exists()) filesToZip.push("vendor-licenses.txt");
90
155
  const migrationsDest = path.resolve(buildDir, "migrations");
91
156
  if (fs.existsSync(migrationsDest)) filesToZip.push("migrations");
92
157
  const seedsDest = path.resolve(buildDir, "seeds");
93
158
  if (fs.existsSync(seedsDest)) filesToZip.push("seeds");
94
- execFileSync("tar", [
159
+ Bun.spawnSync([
160
+ "tar",
95
161
  "-a",
96
162
  "-cf",
97
163
  zipName,
98
164
  ...filesToZip
99
165
  ], {
100
166
  cwd: buildDir,
101
- stdio: "inherit"
167
+ stdio: [
168
+ "inherit",
169
+ "inherit",
170
+ "inherit"
171
+ ]
102
172
  });
103
173
  console.log(`Build Complete: ${manifest.id} v${pkg.version} → ${zipName}`);
104
174
  }
105
175
  }
106
176
  };
107
177
  }
178
+ /**
179
+ * Generates CLI argument parameters for bundling server-side Elysia API scripts (`src/api.ts`) via
180
+ * Bun.
181
+ *
182
+ * @param entryPath - Absolute file path to the server entry script (`src/api.ts`).
183
+ * @param outputPath - Absolute destination file path for the bundled output (`build/api.js`).
184
+ * @param developmentBuild - Indicates whether to enable external sourcemaps or minification.
185
+ * @returns Array of command line arguments for running `bun build`.
186
+ */
108
187
  function createAddonServerBuildArguments(entryPath, outputPath, developmentBuild) {
109
188
  return [
110
189
  "build",
@@ -112,9 +191,17 @@ function createAddonServerBuildArguments(entryPath, outputPath, developmentBuild
112
191
  "--target=bun",
113
192
  "--format=esm",
114
193
  `--outfile=${outputPath}`,
115
- developmentBuild ? "--sourcemap=external" : "--minify"
194
+ developmentBuild ? "--sourcemap=inline" : "--minify"
116
195
  ];
117
196
  }
197
+ /**
198
+ * Cryptographically signs an addon manifest using RSA-SHA256 over all archive file contents.
199
+ *
200
+ * @param manifest - Unsigned or base addon manifest.
201
+ * @param files - List of archive file paths and raw contents to digest.
202
+ * @param privateKey - RSA private key in PEM format.
203
+ * @returns Updated {@link AddonManifest} containing an RSA signature block.
204
+ */
118
205
  function signAddonManifest(manifest, files, privateKey) {
119
206
  if (!manifest.publisher?.id) throw new Error("Signed addons require manifest.publisher.id");
120
207
  const unsigned = {
@@ -126,28 +213,37 @@ function signAddonManifest(manifest, files, privateKey) {
126
213
  }
127
214
  };
128
215
  const hash = crypto.createHash("sha256");
129
- for (const file of [...files].sort((a, b) => a.path.localeCompare(b.path))) {
216
+ for (const file of [...files].toSorted((a, b) => a.path.localeCompare(b.path))) {
130
217
  hash.update(file.path);
131
218
  hash.update("\0");
132
219
  hash.update(file.path === "manifest.json" ? stableStringify(unsigned) : file.contents);
133
220
  hash.update("\0");
134
221
  }
135
222
  const digest = hash.digest("hex");
223
+ const normalizedKey = privateKey.replace(/\\n/g, "\n").trim();
136
224
  return {
137
225
  ...unsigned,
138
226
  signature: {
139
227
  algorithm: "rsa-sha256",
140
228
  digest,
141
- value: crypto.sign("sha256", Buffer.from(digest), privateKey).toString("base64url")
229
+ value: crypto.sign("sha256", Buffer.from(digest), normalizedKey).toString("base64url")
142
230
  }
143
231
  };
144
232
  }
233
+ /**
234
+ * Resolves the required RSA signing key for database-bearing addons.
235
+ *
236
+ * @param signingPrivateKey - Provided signing key or undefined.
237
+ * @param developmentBuild - Whether the current build is targeting development mode.
238
+ * @returns Resolved signing key string or undefined (in dev builds).
239
+ * @throws {@link Error} If building a database-bearing addon in production without a signing key.
240
+ */
145
241
  function requireAddonSigningKey(signingPrivateKey, developmentBuild) {
146
242
  if (signingPrivateKey) return signingPrivateKey;
147
243
  if (developmentBuild) return void 0;
148
244
  throw new Error("Database-bearing addon builds require JCHAT_ADDON_SIGNING_PRIVATE_KEY");
149
245
  }
150
- function embedCssIntoBundle(buildDir, addonId) {
246
+ function embedCssIntoBundle(buildDir) {
151
247
  const files = fs.readdirSync(buildDir);
152
248
  const cssFile = files.find((f) => f.endsWith(".css"));
153
249
  const jsFile = files.find((f) => f.includes("ui") && f.endsWith(".js"));
@@ -158,34 +254,131 @@ function embedCssIntoBundle(buildDir, addonId) {
158
254
  const js = fs.readFileSync(jsPath, "utf-8");
159
255
  if (css.length < 10) css = "";
160
256
  else {
257
+ css = stripLayer(css, "properties");
258
+ css = stripLayer(css, "base");
161
259
  css = css.replace(/:root\s*\{[^}]+\}/g, "");
260
+ css = css.replace(/:root:not\([^)]+\)\s*\{[^}]+\}/g, "");
162
261
  css = css.replace(/\.dark\s*\{[^}]+\}/g, "");
163
262
  css = css.replace(/\[data-theme=[^\]]+\]\s*\{[^}]+\}/g, "");
164
263
  css = css.replace(/\.dark\s*\[data-theme=[^\]]+\]\s*\{[^}]+\}/g, "");
165
- css = `@scope (#addon-${addonId}) {\n*, ::before, ::after { border-color: var(--border); }\n${css}\n}`;
264
+ css = css.replace(/\.font-(?:lato|playfair|dancing|poppins|jetbrains|quicksand|roboto-serif|audiowide|special-elite|press-start|grenze|righteous|creepster|vast-shadow|syncopate|lobster)\s*\{[^}]+\}/g, "");
265
+ css = css.replace(/--font-(?:lato|playfair|dancing|poppins|jetbrains|quicksand|roboto-serif|audiowide|special-elite|press-start|grenze|righteous|creepster|vast-shadow|syncopate|lobster):[^;]+;/g, "");
266
+ css = css.replace(/[^{}]*\[data-color[^{}]*\{[^}]+\}/g, "");
267
+ css = css.replace(/@property\s+--tw-[^{]+\{[^}]+\}/g, "");
268
+ css = css.replace(/\.loader-dots\s*\{[^}]+\}/g, "");
269
+ css = css.replace(/\.loader-dots\s+span[^{]*\{[^}]+\}/g, "");
270
+ css = css.replace(/@keyframes\s+wave-dots\s*\{[\s\S]*?\n\}/g, "");
271
+ css = css.replace(/@keyframes\s+gradient-border\s*\{[\s\S]*?\n\}/g, "");
272
+ css = css.replace(/\.animate-gradient(?:-border|-text)?\s*\{[^}]+\}/g, "");
273
+ css = css.replace(/\.me\s*\{[^}]+\}/g, "");
274
+ css = css.replace(/\.user-border\s*\{[^}]+\}/g, "");
275
+ css = css.replace(/\.scrollbar-hide[^{]*\{[^}]+\}/g, "");
276
+ css = css.replace(/@layer\s+components(?:\s*\{[^}]*\}|;)/g, "");
277
+ css = minifyCss(css);
166
278
  }
167
- const injection = `
279
+ if (css.trim().length > 0) {
280
+ const injection = `
168
281
  (function() {
169
- if (typeof document !== 'undefined' && ${JSON.stringify(css)}.length > 0) {
170
- const style = document.createElement('style');
171
- style.type = 'text/css';
172
- style.textContent = ${JSON.stringify(css)};
173
- document.head.appendChild(style);
282
+ if (typeof document !== 'undefined') {
283
+ var s = document.createElement('style');
284
+ s.type = 'text/css';
285
+ s.textContent = ${JSON.stringify(css)};
286
+ document.head.appendChild(s);
174
287
  }
175
288
  })();
176
289
  `;
177
- fs.writeFileSync(jsPath, injection + js);
290
+ fs.writeFileSync(jsPath, injection + js);
291
+ }
178
292
  try {
179
293
  fs.unlinkSync(cssPath);
180
294
  } catch {}
181
295
  }
296
+ function stripLayer(css, layerName) {
297
+ const regex = new RegExp(`@layer\\s+${layerName}\\s*\\{`);
298
+ let match = regex.exec(css);
299
+ while (match) {
300
+ const startIdx = match.index;
301
+ const openBraceIdx = startIdx + match[0].length - 1;
302
+ let braceCount = 1;
303
+ let endIdx = -1;
304
+ for (let i = openBraceIdx + 1; i < css.length; i++) if (css[i] === "{") braceCount++;
305
+ else if (css[i] === "}") {
306
+ braceCount--;
307
+ if (braceCount === 0) {
308
+ endIdx = i;
309
+ break;
310
+ }
311
+ }
312
+ if (endIdx === -1) break;
313
+ css = css.slice(0, startIdx) + css.slice(endIdx + 1);
314
+ match = regex.exec(css);
315
+ }
316
+ return css;
317
+ }
318
+ function minifyCss(css) {
319
+ return css.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s+/g, " ").replace(/\s*([{};:,>])\s*/g, "$1").replace(/;}/g, "}").trim();
320
+ }
321
+ function sortValue(child) {
322
+ if (Array.isArray(child)) return child.map(sortValue);
323
+ if (child && typeof child === "object") return Object.fromEntries(Object.entries(child).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortValue(nested)]));
324
+ return child;
325
+ }
182
326
  function stableStringify(value) {
183
- const sortValue = (child) => {
184
- if (Array.isArray(child)) return child.map(sortValue);
185
- if (child && typeof child === "object") return Object.fromEntries(Object.entries(child).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortValue(nested)]));
186
- return child;
187
- };
188
327
  return JSON.stringify(sortValue(value));
189
328
  }
329
+ async function generateAddonVendorLicenses(addonDir, addonName) {
330
+ const title = addonName ? `${addonName} Addon` : "JChat Addon";
331
+ try {
332
+ const proc = Bun.spawn([
333
+ "bun",
334
+ "pm",
335
+ "licenses",
336
+ "--json",
337
+ "--prod"
338
+ ], {
339
+ cwd: addonDir,
340
+ stdout: "pipe",
341
+ stderr: "pipe"
342
+ });
343
+ const output = await new Response(proc.stdout).text();
344
+ await proc.exited;
345
+ const data = JSON.parse(output);
346
+ const lines = [
347
+ "================================================================================",
348
+ `${title} - Third-Party Vendor Licenses & Open Source Attribution`,
349
+ "================================================================================",
350
+ "This distribution incorporates open-source libraries and software components.",
351
+ "Their licenses and attributions are listed below.",
352
+ "================================================================================",
353
+ ""
354
+ ];
355
+ let totalPackages = 0;
356
+ const sortedCategories = Object.keys(data).toSorted((a, b) => a.localeCompare(b));
357
+ for (const licenseCategory of sortedCategories) {
358
+ const packages = data[licenseCategory];
359
+ if (!packages || packages.length === 0) continue;
360
+ lines.push(`\n## License: ${licenseCategory} (${packages.length} packages)\n`);
361
+ for (const pkg of packages) {
362
+ totalPackages++;
363
+ lines.push(`- Package: ${pkg.name}@${pkg.versions.join(", ")}`);
364
+ if (pkg.description) lines.push(` Description: ${pkg.description}`);
365
+ if (pkg.author) lines.push(` Author: ${pkg.author}`);
366
+ if (pkg.homepage) lines.push(` Homepage: ${pkg.homepage}`);
367
+ }
368
+ }
369
+ lines.splice(5, 0, `Total Open-Source Dependencies: ${totalPackages}\n`);
370
+ return lines.join("\n") + "\n";
371
+ } catch {
372
+ return [
373
+ "================================================================================",
374
+ `${title} - Third-Party Vendor Licenses & Open Source Attribution`,
375
+ "================================================================================",
376
+ "This distribution incorporates open-source libraries and software components.",
377
+ "See individual package.json files and dependencies for specific license details.",
378
+ "================================================================================",
379
+ ""
380
+ ].join("\n");
381
+ }
382
+ }
190
383
  //#endregion
191
384
  export { createAddonServerBuildArguments, jchatAddon, requireAddonSigningKey, signAddonManifest };
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@jchat/addon-sdk",
3
- "version": "1.0.0-alpha.3",
3
+ "version": "1.0.0-alpha.31",
4
4
  "private": false,
5
+ "description": "JChat Addon SDK for building JChat addons.",
5
6
  "keywords": [
6
7
  "addon",
7
8
  "chat",
@@ -11,55 +12,156 @@
11
12
  "sdk",
12
13
  "vite"
13
14
  ],
14
- "license": "Apache-2.0",
15
- "repository": {
16
- "type": "git",
17
- "url": "git+https://github.com/mjjabarullah/jchat.git",
18
- "directory": "packages/addon-sdk"
15
+ "homepage": "https://jchatcloud.com",
16
+ "license": "SEE LICENSE IN LICENSE",
17
+ "bin": {
18
+ "jchat-addon": "./dist/cli.mjs"
19
19
  },
20
20
  "files": [
21
21
  "dist",
22
+ "src/tailwind.css",
23
+ "tsconfig.addon.json",
24
+ "skills",
22
25
  "README.md",
23
- "CHANGELOG.md"
26
+ "CHANGELOG.md",
27
+ "LICENSE"
24
28
  ],
25
29
  "type": "module",
26
- "main": "./dist/index.mjs",
27
- "types": "./dist/index.d.mts",
30
+ "main": "./src/index.ts",
31
+ "types": "./src/index.ts",
28
32
  "exports": {
29
33
  ".": {
30
- "types": "./dist/index.d.mts",
31
- "import": "./dist/index.mjs"
34
+ "types": "./src/index.ts",
35
+ "import": "./src/index.ts",
36
+ "default": "./src/index.ts"
37
+ },
38
+ "./contracts": {
39
+ "types": "./src/contracts.ts",
40
+ "import": "./src/contracts.ts",
41
+ "default": "./src/contracts.ts"
42
+ },
43
+ "./signing": {
44
+ "types": "./src/signing.ts",
45
+ "import": "./src/signing.ts",
46
+ "default": "./src/signing.ts"
47
+ },
48
+ "./cli": {
49
+ "types": "./src/cli.ts",
50
+ "import": "./src/cli.ts",
51
+ "default": "./src/cli.ts"
32
52
  },
33
53
  "./diagnostics": {
34
- "types": "./dist/diagnostics.d.mts",
35
- "import": "./dist/diagnostics.mjs"
54
+ "types": "./src/diagnostics.ts",
55
+ "import": "./src/diagnostics.ts",
56
+ "default": "./src/diagnostics.ts"
57
+ },
58
+ "./testing": {
59
+ "types": "./src/testing.ts",
60
+ "import": "./src/testing.ts",
61
+ "default": "./src/testing.ts"
36
62
  },
37
63
  "./vite": {
38
- "types": "./dist/vite.d.mts",
39
- "import": "./dist/vite.mjs"
40
- }
64
+ "types": "./src/vite.ts",
65
+ "import": "./src/vite.ts",
66
+ "default": "./src/vite.ts"
67
+ },
68
+ "./i18n-validator": {
69
+ "types": "./src/i18n-validator.ts",
70
+ "import": "./src/i18n-validator.ts",
71
+ "default": "./src/i18n-validator.ts"
72
+ },
73
+ "./ui": {
74
+ "style": "./src/tailwind.css",
75
+ "types": "./src/ui.ts",
76
+ "import": "./src/ui.ts",
77
+ "default": "./src/ui.ts"
78
+ },
79
+ "./state": {
80
+ "types": "./src/state.ts",
81
+ "import": "./src/state.ts",
82
+ "default": "./src/state.ts"
83
+ },
84
+ "./tsconfig.json": "./tsconfig.addon.json"
41
85
  },
42
86
  "publishConfig": {
87
+ "main": "./dist/index.mjs",
88
+ "types": "./dist/index.d.mts",
89
+ "exports": {
90
+ ".": {
91
+ "types": "./dist/index.d.mts",
92
+ "import": "./dist/index.mjs"
93
+ },
94
+ "./contracts": {
95
+ "types": "./dist/contracts.d.mts",
96
+ "import": "./dist/contracts.mjs"
97
+ },
98
+ "./signing": {
99
+ "types": "./dist/signing.d.mts",
100
+ "import": "./dist/signing.mjs"
101
+ },
102
+ "./cli": {
103
+ "types": "./dist/cli.d.mts",
104
+ "import": "./dist/cli.mjs"
105
+ },
106
+ "./diagnostics": {
107
+ "types": "./dist/diagnostics.d.mts",
108
+ "import": "./dist/diagnostics.mjs"
109
+ },
110
+ "./testing": {
111
+ "types": "./dist/testing.d.mts",
112
+ "import": "./dist/testing.mjs"
113
+ },
114
+ "./vite": {
115
+ "types": "./dist/vite.d.mts",
116
+ "import": "./dist/vite.mjs"
117
+ },
118
+ "./i18n-validator": {
119
+ "types": "./dist/i18n-validator.d.mts",
120
+ "import": "./dist/i18n-validator.mjs"
121
+ },
122
+ "./ui": {
123
+ "style": "./src/tailwind.css",
124
+ "types": "./dist/ui.d.mts",
125
+ "import": "./dist/ui.mjs"
126
+ },
127
+ "./state": {
128
+ "types": "./dist/state.d.mts",
129
+ "import": "./dist/state.mjs"
130
+ },
131
+ "./tsconfig.json": "./tsconfig.addon.json"
132
+ },
43
133
  "access": "public"
44
134
  },
45
135
  "scripts": {
46
136
  "build": "tsdown",
47
- "lint": "oxlint . --config=../../oxlint.json",
137
+ "lint": "oxlint .",
48
138
  "format": "oxfmt . --write",
49
- "typecheck": "tsc --noEmit",
50
- "prepack": "bun run build"
139
+ "test": "bun test",
140
+ "typecheck": "bun check"
141
+ },
142
+ "dependencies": {
143
+ "@casl/ability": "catalog:",
144
+ "@casl/react": "catalog:",
145
+ "lucide-react": "catalog:"
51
146
  },
52
147
  "devDependencies": {
53
- "@jchat/icon": "workspace:*",
148
+ "@jchat/ui": "workspace:*",
149
+ "@tailwindcss/vite": "catalog:",
150
+ "@tanstack/react-query": "catalog:",
151
+ "@types/bun": "catalog:",
54
152
  "@types/react": "catalog:",
55
153
  "elysia": "catalog:",
56
- "kysely": "^catalog:",
57
- "tsdown": "^0.22.14",
154
+ "jotai": "catalog:",
155
+ "kysely": "catalog:",
156
+ "tsdown": "catalog:",
58
157
  "vite": "catalog:"
59
158
  },
60
159
  "peerDependencies": {
160
+ "@tailwindcss/vite": "catalog:",
161
+ "@tanstack/react-query": "catalog:",
61
162
  "elysia": "catalog:",
62
- "kysely": "^catalog:",
163
+ "jotai": "catalog:",
164
+ "kysely": "catalog:",
63
165
  "react": "catalog:",
64
166
  "vite": "catalog:"
65
167
  }