@jchat/addon-sdk 1.0.0-alpha.2 → 1.0.0-alpha.4

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,5 +1,18 @@
1
1
  # @jchat/addon-sdk
2
2
 
3
+ ## 1.0.0-alpha.4
4
+
5
+ ### Patch Changes
6
+
7
+ - ada430f: Formatted type declarations in the Addon SDK to align with project style guidelines.
8
+
9
+ ## 1.0.0-alpha.3
10
+
11
+ ### Patch Changes
12
+
13
+ - f7a80fc: - Added `getAddonSdkVersion()` utility export to allow addons and the sandbox environment to safely resolve the runtime SDK version.
14
+ - Updated sandbox developer scripts and Dockerfiles to correctly mount and execute the development environment.
15
+
3
16
  ## 1.0.0-alpha.2
4
17
 
5
18
  ## 1.0.0-alpha.1
package/README.md CHANGED
@@ -40,6 +40,30 @@ export default {
40
40
  }
41
41
  ```
42
42
 
43
+ ## Database Architecture & Schema Isolation
44
+
45
+ JChat database-bearing addons use **Kysely** for server-side database access:
46
+
47
+ - **0 Bundle Overhead**: Table definitions are pure TypeScript interfaces (`src/db.ts`), resulting in 0 runtime JavaScript bundle footprint.
48
+ - **Shared `addons` Schema**: All addon tables are placed inside the dedicated `"addons"` schema (e.g. `addons.DjDropTracks`, `addons.PollwisePolls`, `addons.GlimpseStories`), keeping them cleanly isolated from core `public` application tables without requiring dynamic PostgreSQL role creation (`CREATE ROLE`).
49
+ - **Mandatory Table Naming**: Table names **must start with a Capital letter** and **must be prefixed with your capitalized `addonId`** (e.g. `addons.MyAddonSettings`). Unprefixed tables are rejected by the host migration validator.
50
+ - **SQL Migrations**: Addon migrations are stored as plain SQL files (`migrations/001_*.sql`) listed in `manifest.ts` under `server.migrations`.
51
+ - **ID Column Convention**: Use `text` / `varchar(36)` for host-referencing IDs (`siteId`, `roomId`, `userId`) to ensure driver-agnostic, cast-free query execution with UUID v7 strings.
52
+
53
+ ```ts
54
+ import type { AddonDatabase } from "@jchat/addon-sdk"
55
+
56
+ export interface MyAddonDatabase {
57
+ MyAddonSettings: {
58
+ id: string
59
+ siteId: string
60
+ createdAt: Date
61
+ }
62
+ }
63
+
64
+ export type MyAddonContext = AddonServerContext<MyAddonDatabase>
65
+ ```
66
+
43
67
  ## License
44
68
 
45
69
  Apache-2.0
@@ -1,22 +1,69 @@
1
1
  import { t as AddonManifest } from "./contracts.mjs";
2
2
  //#region src/diagnostics.d.ts
3
+ /**
4
+ * Diagnostic result status indicator for addon validation checks. - `"pass"`: The diagnostic check
5
+ * passed successfully. - `"warning"`: Non-critical warning (e.g. source maps present in
6
+ * production). - `"error"`: Critical failure blocking addon installation or distribution.
7
+ */
3
8
  type AddonDiagnosticStatus = "pass" | "warning" | "error";
9
+ /** Represents an individual diagnostic check result for an addon package. */
4
10
  interface AddonPackageDiagnostic {
11
+ /** Unique identifier for the diagnostic check (e.g. `"jchat"`, `"package-size"`). */
5
12
  id: string;
13
+ /** Human-readable title for the diagnostic check. */
6
14
  label: string;
15
+ /** Severity status outcome of the check. */
7
16
  status: AddonDiagnosticStatus;
17
+ /** Descriptive message or metric value providing check details. */
8
18
  message: string;
9
19
  }
20
+ /** Options required to run diagnostic validation on an addon build package. */
10
21
  interface AddonPackageDiagnosticOptions {
22
+ /** Absolute path to the compiled addon build output directory (`build/`). */
11
23
  buildDir: string;
24
+ /** Parsed addon manifest object (`manifest.json`). */
12
25
  manifest: AddonManifest;
26
+ /** Semantic version of the host JChat platform instance. */
13
27
  jchatVersion: string;
28
+ /** Semantic version of the `@jchat/addon-sdk` package. */
14
29
  addonSdkVersion: string;
30
+ /** Whether the diagnostic target is a production `.zip` package build. Defaults to `false`. */
15
31
  productionPackage?: boolean;
32
+ /** Maximum allowable package size in bytes. Defaults to 25MB (`26,214,400` bytes). */
16
33
  maxBytes?: number;
17
34
  }
35
+ /**
36
+ * Constructs a semantic version compatibility range covering all minor/patch versions of the
37
+ * current major version.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * createCompatibleMajorRange("1.4.2") // returns ">=1.4.2 <2.0.0"
42
+ * ```
43
+ *
44
+ * @param version - Valid semver string (e.g. `"1.2.0"`).
45
+ * @returns Semver range string matching the current major series (e.g. `">=1.2.0 <2.0.0"`).
46
+ * @throws {@link Error} If the input is not a valid semantic version string.
47
+ */
18
48
  declare function createCompatibleMajorRange(version: string): string;
49
+ /**
50
+ * Performs comprehensive diagnostic validation checks on an addon package build directory.
51
+ *
52
+ * Validates version compatibility ranges, verifies required build files (frontend/server bundles,
53
+ * migrations, seeds), checks total package size limits, flags production source maps, and verifies
54
+ * publisher digital signatures.
55
+ *
56
+ * @param options - Configuration options specifying build directory, manifest, and environment
57
+ * versions.
58
+ * @returns Array of {@link AddonPackageDiagnostic} results.
59
+ */
19
60
  declare function diagnoseAddonPackage(options: AddonPackageDiagnosticOptions): AddonPackageDiagnostic[];
61
+ /**
62
+ * Checks whether any diagnostic check in a diagnostic list returned a critical error.
63
+ *
64
+ * @param diagnostics - Array of diagnostic check results to evaluate.
65
+ * @returns `true` if at least one check has `status === "error"`, otherwise `false`.
66
+ */
20
67
  declare function hasAddonDiagnosticErrors(diagnostics: readonly AddonPackageDiagnostic[]): boolean;
21
68
  //#endregion
22
69
  export { AddonDiagnosticStatus, AddonPackageDiagnostic, AddonPackageDiagnosticOptions, createCompatibleMajorRange, diagnoseAddonPackage, hasAddonDiagnosticErrors };
@@ -1,6 +1,19 @@
1
1
  import * as fs$1 from "node:fs";
2
2
  import * as path$1 from "node:path";
3
3
  //#region src/diagnostics.ts
4
+ /**
5
+ * Constructs a semantic version compatibility range covering all minor/patch versions of the
6
+ * current major version.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * createCompatibleMajorRange("1.4.2") // returns ">=1.4.2 <2.0.0"
11
+ * ```
12
+ *
13
+ * @param version - Valid semver string (e.g. `"1.2.0"`).
14
+ * @returns Semver range string matching the current major series (e.g. `">=1.2.0 <2.0.0"`).
15
+ * @throws {@link Error} If the input is not a valid semantic version string.
16
+ */
4
17
  function createCompatibleMajorRange(version) {
5
18
  try {
6
19
  Bun.semver.order(version, version);
@@ -12,6 +25,17 @@ function createCompatibleMajorRange(version) {
12
25
  if (!Number.isSafeInteger(major)) throw new Error(`Invalid semantic version: ${version}`);
13
26
  return `>=${version} <${major + 1}.0.0`;
14
27
  }
28
+ /**
29
+ * Performs comprehensive diagnostic validation checks on an addon package build directory.
30
+ *
31
+ * Validates version compatibility ranges, verifies required build files (frontend/server bundles,
32
+ * migrations, seeds), checks total package size limits, flags production source maps, and verifies
33
+ * publisher digital signatures.
34
+ *
35
+ * @param options - Configuration options specifying build directory, manifest, and environment
36
+ * versions.
37
+ * @returns Array of {@link AddonPackageDiagnostic} results.
38
+ */
15
39
  function diagnoseAddonPackage(options) {
16
40
  const { buildDir, manifest } = options;
17
41
  const diagnostics = [];
@@ -59,6 +83,18 @@ function diagnoseAddonPackage(options) {
59
83
  status: totalBytes <= maxBytes ? "pass" : "error",
60
84
  message: `${totalBytes} of ${maxBytes} bytes`
61
85
  });
86
+ const addonPermPrefix = `addon.${manifest.id}.`;
87
+ const invalidPerms = Array.from(/* @__PURE__ */ new Set([
88
+ ...manifest.accessPermission ? [manifest.accessPermission] : [],
89
+ ...manifest.permissions ?? [],
90
+ ...manifest.permissionDefinitions?.map((d) => d.name) ?? []
91
+ ])).filter((perm) => !perm.startsWith(addonPermPrefix));
92
+ diagnostics.push({
93
+ id: "permission-namespacing",
94
+ label: "Permission namespacing",
95
+ status: invalidPerms.length === 0 ? "pass" : "error",
96
+ message: invalidPerms.length === 0 ? `All declared permissions start with ${addonPermPrefix}` : `Permission(s) do not follow naming convention ${addonPermPrefix}*: ${invalidPerms.join(", ")}`
97
+ });
62
98
  const sourceMaps = files.filter((file) => file.endsWith(".map"));
63
99
  diagnostics.push({
64
100
  id: "source-maps",
@@ -81,9 +117,24 @@ function diagnoseAddonPackage(options) {
81
117
  });
82
118
  return diagnostics;
83
119
  }
120
+ /**
121
+ * Checks whether any diagnostic check in a diagnostic list returned a critical error.
122
+ *
123
+ * @param diagnostics - Array of diagnostic check results to evaluate.
124
+ * @returns `true` if at least one check has `status === "error"`, otherwise `false`.
125
+ */
84
126
  function hasAddonDiagnosticErrors(diagnostics) {
85
127
  return diagnostics.some(({ status }) => status === "error");
86
128
  }
129
+ /**
130
+ * Evaluates semantic version compatibility between a target version and a semver range string.
131
+ *
132
+ * @param id - Diagnostic check identifier.
133
+ * @param label - Diagnostic check label.
134
+ * @param version - Environment component version string.
135
+ * @param range - Expected semver range string from manifest compatibility declarations.
136
+ * @returns An {@link AddonPackageDiagnostic} result object.
137
+ */
87
138
  function compatibilityDiagnostic(id, label, version, range) {
88
139
  const compatible = Boolean(range && Bun.semver.satisfies(version, range));
89
140
  return {
@@ -93,12 +144,26 @@ function compatibilityDiagnostic(id, label, version, range) {
93
144
  message: range ? `${version} ${compatible ? "satisfies" : "does not satisfy"} ${range}` : "Compatibility range is missing"
94
145
  };
95
146
  }
147
+ /**
148
+ * Safely resolves a relative build file reference within a target build directory, guarding against
149
+ * directory traversal attacks.
150
+ *
151
+ * @param buildDir - Absolute path to the build directory.
152
+ * @param reference - Relative file path declared in manifest.
153
+ * @returns Resolved absolute file path if safe and inside `buildDir`, or `null` if unsafe.
154
+ */
96
155
  function resolveBuildFile(buildDir, reference) {
97
156
  if (path$1.isAbsolute(reference) || reference.includes("\\") || reference.split("/").includes("..")) return null;
98
157
  const target = path$1.resolve(buildDir, ...reference.replace(/^\.\//, "").split("/"));
99
158
  const relative = path$1.relative(path$1.resolve(buildDir), target);
100
159
  return relative && !relative.startsWith("..") && !path$1.isAbsolute(relative) ? target : null;
101
160
  }
161
+ /**
162
+ * Recursively lists all regular files within a root directory.
163
+ *
164
+ * @param root - Path to search.
165
+ * @returns Array of absolute file paths.
166
+ */
102
167
  function listRegularFiles(root) {
103
168
  if (!fs$1.existsSync(root)) return [];
104
169
  return fs$1.readdirSync(root, {
package/dist/index.d.mts CHANGED
@@ -253,5 +253,19 @@ declare function useAddonSDK(): AddonSDK;
253
253
  declare function useIcons(): {
254
254
  Icons: IconPack;
255
255
  };
256
+ /**
257
+ * Get the version of the addon SDK. This is useful for checking compatibility with the host
258
+ * application.
259
+ *
260
+ * @example
261
+ * ;```tsx
262
+ * import { getAddonSdkVersion } from "@jchat/addon-sdk"
263
+ *
264
+ * console.log(getAddonSdkVersion())
265
+ * ```
266
+ *
267
+ * @returns
268
+ */
269
+ declare function getAddonSdkVersion(): string;
256
270
  //#endregion
257
- export { AddonApi, AddonDatabase, AddonEventListener, AddonFont, AddonJsonBody, type AddonManifest, type AddonPermission, type AddonPermissionDefinition, AddonProps, AddonRequestUser, AddonSDK, AddonSeedDocument, AddonServerContext, AddonServerFactory, AddonUser, type ConfigSchemaField, MOUNT_POINTS, type MountPoint, defineAddonManifest, defineAddonServer, useAddonSDK, useIcons };
271
+ export { AddonApi, AddonDatabase, AddonEventListener, AddonFont, AddonJsonBody, type AddonManifest, type AddonPermission, type AddonPermissionDefinition, AddonProps, AddonRequestUser, AddonSDK, AddonSeedDocument, AddonServerContext, AddonServerFactory, AddonUser, type ConfigSchemaField, MOUNT_POINTS, type MountPoint, defineAddonManifest, defineAddonServer, getAddonSdkVersion, useAddonSDK, useIcons };
package/dist/index.mjs CHANGED
@@ -1,3 +1,6 @@
1
+ //#region package.json
2
+ var version = "1.0.0-alpha.4";
3
+ //#endregion
1
4
  //#region src/contracts.ts
2
5
  /** Valid locations where an addon can be rendered within the Jchat layout. */
3
6
  const MOUNT_POINTS = {
@@ -82,5 +85,21 @@ function useAddonSDK() {
82
85
  function useIcons() {
83
86
  throw new Error("useIcons must be used within the Jchat host environment.");
84
87
  }
88
+ /**
89
+ * Get the version of the addon SDK. This is useful for checking compatibility with the host
90
+ * application.
91
+ *
92
+ * @example
93
+ * ;```tsx
94
+ * import { getAddonSdkVersion } from "@jchat/addon-sdk"
95
+ *
96
+ * console.log(getAddonSdkVersion())
97
+ * ```
98
+ *
99
+ * @returns
100
+ */
101
+ function getAddonSdkVersion() {
102
+ return version;
103
+ }
85
104
  //#endregion
86
- export { MOUNT_POINTS, defineAddonManifest, defineAddonServer, useAddonSDK, useIcons };
105
+ export { MOUNT_POINTS, defineAddonManifest, defineAddonServer, getAddonSdkVersion, useAddonSDK, useIcons };
package/dist/vite.d.mts CHANGED
@@ -2,13 +2,41 @@ import { t as AddonManifest } from "./contracts.mjs";
2
2
  import { Plugin } from "vite";
3
3
  //#region src/vite.d.ts
4
4
  /**
5
- * Vite plugin to configure Jchat addon manifest generation, bundle backend scripts, copy
6
- * migrations, declarative seed data, and zip production build artifacts.
5
+ * Vite plugin for building JChat sandboxed addon extensions.
6
+ *
7
+ * Configures automatic manifest generation (`manifest.json`), bundles server-side API scripts
8
+ * (`src/api.ts`), embeds scoped Tailwind CSS into the frontend bundle, packages database migrations
9
+ * and seed files, copies documentation (`README.md`), signs database-bearing addon manifests, and
10
+ * zips production build artifacts.
11
+ *
12
+ * @example
13
+ * ;```ts
14
+ * import { jchatAddon } from "@jchat/addon-sdk/vite"
15
+ * import manifest from "./src/manifest"
16
+ * import { defineConfig } from "vite"
17
+ *
18
+ * export default defineConfig({
19
+ * plugins: [jchatAddon({ manifest })]
20
+ * })
21
+ * ```
22
+ *
23
+ * @param options - Configuration options for the JChat addon Vite plugin.
24
+ * @returns A Vite {@link Plugin} instance configured for addon compilation.
7
25
  */
8
26
  declare function jchatAddon(options: JchatAddonPluginOptions): Plugin;
27
+ /** Configuration options for the {@link jchatAddon} Vite plugin. */
9
28
  interface JchatAddonPluginOptions {
29
+ /** The base manifest specification for the addon. */
10
30
  manifest: AddonManifest;
31
+ /**
32
+ * Whether to package the build output into a `.zip` archive upon build completion. Defaults to
33
+ * `true` during production builds and `false` during development builds.
34
+ */
11
35
  zip?: boolean;
36
+ /**
37
+ * Optional RSA private key string used to cryptographically sign database-bearing addons. If
38
+ * omitted, falls back to the `JCHAT_ADDON_SIGNING_PRIVATE_KEY` environment variable.
39
+ */
12
40
  signingPrivateKey?: string;
13
41
  /**
14
42
  * Embed Tailwind CSS output into the JS bundle and scope it to the addon's DOM container.
@@ -16,11 +44,36 @@ interface JchatAddonPluginOptions {
16
44
  */
17
45
  css?: boolean;
18
46
  }
47
+ /**
48
+ * Generates CLI argument parameters for bundling server-side Elysia API scripts (`src/api.ts`) via
49
+ * Bun.
50
+ *
51
+ * @param entryPath - Absolute file path to the server entry script (`src/api.ts`).
52
+ * @param outputPath - Absolute destination file path for the bundled output (`build/api.js`).
53
+ * @param developmentBuild - Indicates whether to enable external sourcemaps or minification.
54
+ * @returns Array of command line arguments for running `bun build`.
55
+ */
19
56
  declare function createAddonServerBuildArguments(entryPath: string, outputPath: string, developmentBuild: boolean): string[];
57
+ /**
58
+ * Cryptographically signs an addon manifest using RSA-SHA256 over all archive file contents.
59
+ *
60
+ * @param manifest - Unsigned or base addon manifest.
61
+ * @param files - List of archive file paths and raw contents to digest.
62
+ * @param privateKey - RSA private key in PEM format.
63
+ * @returns Updated {@link AddonManifest} containing an RSA signature block.
64
+ */
20
65
  declare function signAddonManifest(manifest: AddonManifest, files: readonly {
21
66
  path: string;
22
67
  contents: Buffer;
23
68
  }[], privateKey: string): AddonManifest;
69
+ /**
70
+ * Resolves the required RSA signing key for database-bearing addons.
71
+ *
72
+ * @param signingPrivateKey - Provided signing key or undefined.
73
+ * @param developmentBuild - Whether the current build is targeting development mode.
74
+ * @returns Resolved signing key string or undefined (in dev builds).
75
+ * @throws {@link Error} If building a database-bearing addon in production without a signing key.
76
+ */
24
77
  declare function requireAddonSigningKey(signingPrivateKey: string | undefined, developmentBuild: boolean): string | undefined;
25
78
  //#endregion
26
79
  export { JchatAddonPluginOptions, createAddonServerBuildArguments, jchatAddon, requireAddonSigningKey, signAddonManifest };
package/dist/vite.mjs CHANGED
@@ -4,8 +4,26 @@ import { execFileSync } from "node:child_process";
4
4
  import crypto from "node:crypto";
5
5
  //#region src/vite.ts
6
6
  /**
7
- * Vite plugin to configure Jchat addon manifest generation, bundle backend scripts, copy
8
- * migrations, declarative seed data, and zip production build artifacts.
7
+ * Vite plugin for building JChat sandboxed addon extensions.
8
+ *
9
+ * Configures automatic manifest generation (`manifest.json`), bundles server-side API scripts
10
+ * (`src/api.ts`), embeds scoped Tailwind CSS into the frontend bundle, packages database migrations
11
+ * and seed files, copies documentation (`README.md`), signs database-bearing addon manifests, and
12
+ * zips production build artifacts.
13
+ *
14
+ * @example
15
+ * ;```ts
16
+ * import { jchatAddon } from "@jchat/addon-sdk/vite"
17
+ * import manifest from "./src/manifest"
18
+ * import { defineConfig } from "vite"
19
+ *
20
+ * export default defineConfig({
21
+ * plugins: [jchatAddon({ manifest })]
22
+ * })
23
+ * ```
24
+ *
25
+ * @param options - Configuration options for the JChat addon Vite plugin.
26
+ * @returns A Vite {@link Plugin} instance configured for addon compilation.
9
27
  */
10
28
  function jchatAddon(options) {
11
29
  const { manifest: manifestData } = options;
@@ -81,12 +99,15 @@ function jchatAddon(options) {
81
99
  })), signingPrivateKey);
82
100
  }
83
101
  }
102
+ const readmeSource = path.resolve(rootDir, "README.md");
103
+ if (fs.existsSync(readmeSource)) fs.copyFileSync(readmeSource, path.resolve(buildDir, "README.md"));
84
104
  const manifestJson = JSON.stringify(manifest, null, 2);
85
105
  fs.writeFileSync(path.resolve(buildDir, "manifest.json"), manifestJson);
86
106
  if (shouldZip) {
87
107
  const zipName = `${manifest.id}-${pkg.version}.zip`;
88
108
  const filesToZip = ["manifest.json", bundleFile];
89
109
  if (fs.existsSync(path.resolve(buildDir, "api.js"))) filesToZip.push("api.js");
110
+ if (fs.existsSync(path.resolve(buildDir, "README.md"))) filesToZip.push("README.md");
90
111
  const migrationsDest = path.resolve(buildDir, "migrations");
91
112
  if (fs.existsSync(migrationsDest)) filesToZip.push("migrations");
92
113
  const seedsDest = path.resolve(buildDir, "seeds");
@@ -105,6 +126,15 @@ function jchatAddon(options) {
105
126
  }
106
127
  };
107
128
  }
129
+ /**
130
+ * Generates CLI argument parameters for bundling server-side Elysia API scripts (`src/api.ts`) via
131
+ * Bun.
132
+ *
133
+ * @param entryPath - Absolute file path to the server entry script (`src/api.ts`).
134
+ * @param outputPath - Absolute destination file path for the bundled output (`build/api.js`).
135
+ * @param developmentBuild - Indicates whether to enable external sourcemaps or minification.
136
+ * @returns Array of command line arguments for running `bun build`.
137
+ */
108
138
  function createAddonServerBuildArguments(entryPath, outputPath, developmentBuild) {
109
139
  return [
110
140
  "build",
@@ -112,9 +142,17 @@ function createAddonServerBuildArguments(entryPath, outputPath, developmentBuild
112
142
  "--target=bun",
113
143
  "--format=esm",
114
144
  `--outfile=${outputPath}`,
115
- developmentBuild ? "--sourcemap=external" : "--minify"
145
+ developmentBuild ? "--sourcemap=inline" : "--minify"
116
146
  ];
117
147
  }
148
+ /**
149
+ * Cryptographically signs an addon manifest using RSA-SHA256 over all archive file contents.
150
+ *
151
+ * @param manifest - Unsigned or base addon manifest.
152
+ * @param files - List of archive file paths and raw contents to digest.
153
+ * @param privateKey - RSA private key in PEM format.
154
+ * @returns Updated {@link AddonManifest} containing an RSA signature block.
155
+ */
118
156
  function signAddonManifest(manifest, files, privateKey) {
119
157
  if (!manifest.publisher?.id) throw new Error("Signed addons require manifest.publisher.id");
120
158
  const unsigned = {
@@ -142,6 +180,14 @@ function signAddonManifest(manifest, files, privateKey) {
142
180
  }
143
181
  };
144
182
  }
183
+ /**
184
+ * Resolves the required RSA signing key for database-bearing addons.
185
+ *
186
+ * @param signingPrivateKey - Provided signing key or undefined.
187
+ * @param developmentBuild - Whether the current build is targeting development mode.
188
+ * @returns Resolved signing key string or undefined (in dev builds).
189
+ * @throws {@link Error} If building a database-bearing addon in production without a signing key.
190
+ */
145
191
  function requireAddonSigningKey(signingPrivateKey, developmentBuild) {
146
192
  if (signingPrivateKey) return signingPrivateKey;
147
193
  if (developmentBuild) return void 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jchat/addon-sdk",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.4",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "addon",
@@ -19,7 +19,6 @@
19
19
  },
20
20
  "files": [
21
21
  "dist",
22
- "src",
23
22
  "README.md",
24
23
  "CHANGELOG.md"
25
24
  ],
@@ -45,7 +44,7 @@
45
44
  },
46
45
  "scripts": {
47
46
  "build": "tsdown",
48
- "lint": "oxlint . --config=../../oxlint.json",
47
+ "lint": "oxlint .",
49
48
  "format": "oxfmt . --write",
50
49
  "typecheck": "tsc --noEmit",
51
50
  "prepack": "bun run build"
@@ -1,127 +0,0 @@
1
- export type AddonPermission = string;
2
- /**
3
- * Defines a single configuration field for an addon's settings panel. These are shown to site
4
- * admins in the Jchat dashboard.
5
- */
6
- export interface ConfigSchemaField {
7
- /** Unique key used to store and retrieve the value in `getConfig` */
8
- key: string;
9
- /** Data type for validation and UI rendering */
10
- type: "string" | "number" | "boolean";
11
- /** Human-readable label shown in the settings UI */
12
- label: string;
13
- /** If true, the admin must provide a value before saving */
14
- required?: boolean;
15
- /** Whether the value is sensitive (encrypted at rest and masked in the UI) */
16
- secret?: boolean;
17
- /** Default value pre-filled in the settings form for new installations */
18
- default?: string | number | boolean;
19
- }
20
- /** Definition of a custom permission introduced by an addon. */
21
- export interface AddonPermissionDefinition {
22
- /** Permission identifier (recommended: `addon.<id>.<action>`) */
23
- name: string;
24
- /** Short, human-readable name for the permission */
25
- label: string;
26
- /** Detailed description of what the permission grants (shown in Rank editor) */
27
- description: string;
28
- }
29
- /** Valid locations where an addon can be rendered within the Jchat layout. */
30
- export declare const MOUNT_POINTS: {
31
- /** Top of the main chat column */
32
- readonly CHAT_HEADER: "chat-header";
33
- /** Below the main chat header, above messages */
34
- readonly CHAT_TOOLBAR: "chat-toolbar";
35
- /** The persistent right-side sidebar */
36
- readonly CHAT_SIDEBAR: "chat-sidebar";
37
- /** Top of the left sidebar (room list) */
38
- readonly SIDEBAR_TOP: "sidebar-top";
39
- /** Bottom of the left sidebar */
40
- readonly SIDEBAR_BOTTOM: "sidebar-bottom";
41
- /** Action list shown when clicking a user's avatar */
42
- readonly USER_POPOVER_ACTIONS: "user-popover-actions";
43
- /** Menu shown when right-clicking a message */
44
- readonly MESSAGE_CONTEXT_MENU: "message-context-menu";
45
- /** Floating overlay rendered on top of the message stream */
46
- readonly MESSAGE_FEED_OVERLAY: "message-feed-overlay";
47
- /** Main admin dashboard area */
48
- readonly ADMIN_PANEL: "admin-panel";
49
- /** User or site settings dashboard area */
50
- readonly SETTINGS_PANEL: "settings-panel";
51
- /** The 'plus' (+) menu in the message composer */
52
- readonly CHAT_PLUS_MENU: "chat-plus-menu";
53
- /** Custom tab in the emoji/gif selection panel */
54
- readonly EMOJI_PICKER_GIF_TAB: "emoji-picker-gif-tab";
55
- /** Full-screen or modal dialog specifically for TubeScan */
56
- readonly TUBESCAN_DIALOG: "tubescan-dialog";
57
- };
58
- /** Union type of all valid addon mount points. */
59
- export type MountPoint = (typeof MOUNT_POINTS)[keyof typeof MOUNT_POINTS];
60
- /**
61
- * The `manifest.json` schema required for every Jchat addon. This file describes how the addon is
62
- * identified and mounted.
63
- */
64
- export interface AddonManifest {
65
- /** Unique kebab-case addon identifier (must match the folder name) */
66
- id: string;
67
- /** Human-readable addon name */
68
- name: string;
69
- /** Semver version string (e.g. `1.2.0`) */
70
- version: string;
71
- /** Brief summary of what the addon does */
72
- description?: string;
73
- /** Author name, organization, or GitHub handle */
74
- author?: string;
75
- /** Support or documentation URL */
76
- homepage?: string;
77
- /** SPDX license identifier (e.g. `MIT`) */
78
- license?: string;
79
- /** Host and SDK versions this directly executed plugin was built and tested against */
80
- compatibility: {
81
- /** Supported JChat versions as a semantic-version range, for example `^1.0.0` */
82
- jchat: string;
83
- /** Supported `@jchat/addon-sdk` versions as a semantic-version range */
84
- addonSdk: string;
85
- };
86
- /** Identity of the trusted publisher that signed this package. Required when migrations exist */
87
- publisher?: {
88
- id: string;
89
- };
90
- /** Signature over the canonical archive digest. Required when migrations exist */
91
- signature?: {
92
- algorithm: "rsa-sha256";
93
- digest: string;
94
- value: string;
95
- };
96
- /** Configuration for the React-based frontend bundle */
97
- frontend?: {
98
- /** Relative path to the pre-compiled ESM bundle (created by Vite) */
99
- bundle: string;
100
- /** List of UI locations where this addon should be active */
101
- mountPoints: MountPoint[];
102
- /** Optional path to a specific UI for the settings panel */
103
- settings?: string;
104
- /** Additional shared packages this addon imports from the host */
105
- externals?: string[];
106
- };
107
- /** Configuration for the server-side API bundle */
108
- server?: {
109
- /** Relative path to the pre-compiled server bundle */
110
- bundle?: string;
111
- /** List of SQL files to run (in order) to set up the addon's database tables */
112
- migrations?: string[];
113
- /** List of declarative JSON master-data files to apply once, in order */
114
- seeds?: string[];
115
- };
116
- /**
117
- * The minimum permission required to see or use this addon. If provided, the host gates
118
- * visibility in the UI and access to all server routes.
119
- */
120
- accessPermission?: AddonPermission;
121
- /** Full list of all permissions used by this addon for informational purposes */
122
- permissions?: AddonPermission[];
123
- /** Custom permissions that should be registered with the host application on installation */
124
- permissionDefinitions?: AddonPermissionDefinition[];
125
- /** Settings form structure shown to site admins. Values are stored encrypted per site */
126
- configSchema?: ConfigSchemaField[];
127
- }