@jchat/addon-sdk 1.0.0-alpha.3 → 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 +6 -0
- package/README.md +24 -0
- package/dist/diagnostics.d.mts +47 -0
- package/dist/diagnostics.mjs +65 -0
- package/dist/index.mjs +1 -1
- package/dist/vite.d.mts +55 -2
- package/dist/vite.mjs +49 -3
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
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
|
package/dist/diagnostics.d.mts
CHANGED
|
@@ -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 };
|
package/dist/diagnostics.mjs
CHANGED
|
@@ -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.mjs
CHANGED
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
|
|
6
|
-
*
|
|
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
|
|
8
|
-
*
|
|
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=
|
|
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.
|
|
3
|
+
"version": "1.0.0-alpha.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"addon",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsdown",
|
|
47
|
-
"lint": "oxlint .
|
|
47
|
+
"lint": "oxlint .",
|
|
48
48
|
"format": "oxfmt . --write",
|
|
49
49
|
"typecheck": "tsc --noEmit",
|
|
50
50
|
"prepack": "bun run build"
|