@jchat/addon-sdk 1.0.0-alpha.4 → 1.0.0-alpha.7
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 +22 -0
- package/LICENSE +18 -196
- package/dist/cli.d.mts +36 -0
- package/dist/cli.mjs +135 -0
- package/dist/contracts.d.mts +16 -24
- package/dist/diagnostics.d.mts +1 -1
- package/dist/diagnostics.mjs +1 -1
- package/dist/index.d.mts +251 -8
- package/dist/index.mjs +9757 -3
- package/dist/ui.d.mts +1 -0
- package/dist/ui.mjs +2 -0
- package/dist/vite.d.mts +2 -0
- package/dist/vite.mjs +70 -23
- package/package.json +29 -3
- package/tsconfig.addon.json +20 -0
package/dist/ui.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@jchat/ui";
|
package/dist/ui.mjs
ADDED
package/dist/vite.d.mts
CHANGED
|
@@ -28,6 +28,8 @@ declare function jchatAddon(options: JchatAddonPluginOptions): Plugin;
|
|
|
28
28
|
interface JchatAddonPluginOptions {
|
|
29
29
|
/** The base manifest specification for the addon. */
|
|
30
30
|
manifest: AddonManifest;
|
|
31
|
+
/** Explicitly declare development mode to permit unsigned database-bearing builds. */
|
|
32
|
+
development?: boolean;
|
|
31
33
|
/**
|
|
32
34
|
* Whether to package the build output into a `.zip` archive upon build completion. Defaults to
|
|
33
35
|
* `true` during production builds and `false` during development builds.
|
package/dist/vite.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { execFileSync } from "node:child_process";
|
|
4
3
|
import crypto from "node:crypto";
|
|
5
4
|
//#region src/vite.ts
|
|
6
5
|
/**
|
|
@@ -33,10 +32,45 @@ function jchatAddon(options) {
|
|
|
33
32
|
name: "jchat-addon",
|
|
34
33
|
apply: "build",
|
|
35
34
|
config(_, env) {
|
|
36
|
-
|
|
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
|
+
"jotai",
|
|
61
|
+
"react-hot-toast",
|
|
62
|
+
"@tanstack/react-query",
|
|
63
|
+
"@jchat/addon-sdk",
|
|
64
|
+
"@jchat/addon-sdk/ui"
|
|
65
|
+
],
|
|
66
|
+
output: { format: "esm" }
|
|
67
|
+
}
|
|
68
|
+
} : {}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
37
71
|
},
|
|
38
72
|
configResolved(config) {
|
|
39
|
-
developmentBuild = config.mode === "development";
|
|
73
|
+
developmentBuild = options.development ?? (config.mode === "development" || process.env.JCHAT_ADDON_DEV === "true" || process.env.NODE_ENV === "development");
|
|
40
74
|
if (shouldZip === void 0) shouldZip = config.mode === "production";
|
|
41
75
|
},
|
|
42
76
|
async writeBundle() {
|
|
@@ -59,9 +93,13 @@ function jchatAddon(options) {
|
|
|
59
93
|
}
|
|
60
94
|
};
|
|
61
95
|
const serverSrcPath = path.resolve(rootDir, "src/api.ts");
|
|
62
|
-
const hasServer =
|
|
96
|
+
const hasServer = await Bun.file(serverSrcPath).exists();
|
|
63
97
|
if (hasServer) {
|
|
64
|
-
|
|
98
|
+
Bun.spawnSync(["bun", ...createAddonServerBuildArguments(serverSrcPath, path.resolve(buildDir, "api.js"), developmentBuild)], { stdio: [
|
|
99
|
+
"inherit",
|
|
100
|
+
"inherit",
|
|
101
|
+
"inherit"
|
|
102
|
+
] });
|
|
65
103
|
manifest = {
|
|
66
104
|
...manifest,
|
|
67
105
|
server: {
|
|
@@ -77,12 +115,15 @@ function jchatAddon(options) {
|
|
|
77
115
|
});
|
|
78
116
|
for (const relativePath of databaseFiles) {
|
|
79
117
|
if (path.isAbsolute(relativePath) || relativePath.includes("\\") || relativePath.split("/").includes("..")) throw new Error(`Unsafe addon database file path: ${relativePath}`);
|
|
80
|
-
const source = path.resolve(rootDir, relativePath);
|
|
81
|
-
if (!fs.existsSync(source) || !fs.statSync(source).isFile()) throw new Error(`Missing addon database file: ${relativePath}`);
|
|
82
118
|
const destination = path.resolve(buildDir, relativePath);
|
|
83
119
|
fs.mkdirSync(path.dirname(destination), { recursive: true });
|
|
84
|
-
fs.copyFileSync(source, destination);
|
|
85
120
|
}
|
|
121
|
+
await Promise.all(databaseFiles.map(async (relativePath) => {
|
|
122
|
+
const source = path.resolve(rootDir, relativePath);
|
|
123
|
+
if (!await Bun.file(source).exists() || !fs.statSync(source).isFile()) throw new Error(`Missing addon database file: ${relativePath}`);
|
|
124
|
+
const destination = path.resolve(buildDir, relativePath);
|
|
125
|
+
return Bun.write(destination, Bun.file(source));
|
|
126
|
+
}));
|
|
86
127
|
if (manifest.server?.migrations?.length || manifest.server?.seeds?.length) {
|
|
87
128
|
const signingPrivateKey = requireAddonSigningKey(options.signingPrivateKey ?? process.env.JCHAT_ADDON_SIGNING_PRIVATE_KEY, developmentBuild);
|
|
88
129
|
if (signingPrivateKey) {
|
|
@@ -93,33 +134,39 @@ function jchatAddon(options) {
|
|
|
93
134
|
...manifest.server?.seeds ?? []
|
|
94
135
|
];
|
|
95
136
|
if (hasServer) archivePaths.push("api.js");
|
|
96
|
-
|
|
137
|
+
const resolvedFiles = await Promise.all(archivePaths.map(async (file) => ({
|
|
97
138
|
path: file,
|
|
98
|
-
contents: file === "manifest.json" ? Buffer.from("") :
|
|
99
|
-
}))
|
|
139
|
+
contents: file === "manifest.json" ? Buffer.from("") : Buffer.from(await Bun.file(path.resolve(buildDir, file)).arrayBuffer())
|
|
140
|
+
})));
|
|
141
|
+
manifest = signAddonManifest(manifest, resolvedFiles, signingPrivateKey);
|
|
100
142
|
}
|
|
101
143
|
}
|
|
102
144
|
const readmeSource = path.resolve(rootDir, "README.md");
|
|
103
|
-
if (
|
|
145
|
+
if (await Bun.file(readmeSource).exists()) await Bun.write(path.resolve(buildDir, "README.md"), Bun.file(readmeSource));
|
|
104
146
|
const manifestJson = JSON.stringify(manifest, null, 2);
|
|
105
|
-
|
|
147
|
+
await Bun.write(path.resolve(buildDir, "manifest.json"), manifestJson);
|
|
106
148
|
if (shouldZip) {
|
|
107
149
|
const zipName = `${manifest.id}-${pkg.version}.zip`;
|
|
108
150
|
const filesToZip = ["manifest.json", bundleFile];
|
|
109
|
-
if (
|
|
110
|
-
if (
|
|
151
|
+
if (await Bun.file(path.resolve(buildDir, "api.js")).exists()) filesToZip.push("api.js");
|
|
152
|
+
if (await Bun.file(path.resolve(buildDir, "README.md")).exists()) filesToZip.push("README.md");
|
|
111
153
|
const migrationsDest = path.resolve(buildDir, "migrations");
|
|
112
154
|
if (fs.existsSync(migrationsDest)) filesToZip.push("migrations");
|
|
113
155
|
const seedsDest = path.resolve(buildDir, "seeds");
|
|
114
156
|
if (fs.existsSync(seedsDest)) filesToZip.push("seeds");
|
|
115
|
-
|
|
157
|
+
Bun.spawnSync([
|
|
158
|
+
"tar",
|
|
116
159
|
"-a",
|
|
117
160
|
"-cf",
|
|
118
161
|
zipName,
|
|
119
162
|
...filesToZip
|
|
120
163
|
], {
|
|
121
164
|
cwd: buildDir,
|
|
122
|
-
stdio:
|
|
165
|
+
stdio: [
|
|
166
|
+
"inherit",
|
|
167
|
+
"inherit",
|
|
168
|
+
"inherit"
|
|
169
|
+
]
|
|
123
170
|
});
|
|
124
171
|
console.log(`Build Complete: ${manifest.id} v${pkg.version} → ${zipName}`);
|
|
125
172
|
}
|
|
@@ -164,7 +211,7 @@ function signAddonManifest(manifest, files, privateKey) {
|
|
|
164
211
|
}
|
|
165
212
|
};
|
|
166
213
|
const hash = crypto.createHash("sha256");
|
|
167
|
-
for (const file of [...files].
|
|
214
|
+
for (const file of [...files].toSorted((a, b) => a.path.localeCompare(b.path))) {
|
|
168
215
|
hash.update(file.path);
|
|
169
216
|
hash.update("\0");
|
|
170
217
|
hash.update(file.path === "manifest.json" ? stableStringify(unsigned) : file.contents);
|
|
@@ -225,12 +272,12 @@ function embedCssIntoBundle(buildDir, addonId) {
|
|
|
225
272
|
fs.unlinkSync(cssPath);
|
|
226
273
|
} catch {}
|
|
227
274
|
}
|
|
275
|
+
function sortValue(child) {
|
|
276
|
+
if (Array.isArray(child)) return child.map(sortValue);
|
|
277
|
+
if (child && typeof child === "object") return Object.fromEntries(Object.entries(child).toSorted(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortValue(nested)]));
|
|
278
|
+
return child;
|
|
279
|
+
}
|
|
228
280
|
function stableStringify(value) {
|
|
229
|
-
const sortValue = (child) => {
|
|
230
|
-
if (Array.isArray(child)) return child.map(sortValue);
|
|
231
|
-
if (child && typeof child === "object") return Object.fromEntries(Object.entries(child).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortValue(nested)]));
|
|
232
|
-
return child;
|
|
233
|
-
};
|
|
234
281
|
return JSON.stringify(sortValue(value));
|
|
235
282
|
}
|
|
236
283
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jchat/addon-sdk",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.7",
|
|
4
4
|
"private": false,
|
|
5
|
+
"description": "JChat Addon SDK for building JChat addons.",
|
|
5
6
|
"keywords": [
|
|
6
7
|
"addon",
|
|
7
8
|
"chat",
|
|
@@ -11,14 +12,18 @@
|
|
|
11
12
|
"sdk",
|
|
12
13
|
"vite"
|
|
13
14
|
],
|
|
14
|
-
"license": "
|
|
15
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
15
16
|
"repository": {
|
|
16
17
|
"type": "git",
|
|
17
18
|
"url": "git+https://github.com/mjjabarullah/jchat.git",
|
|
18
19
|
"directory": "packages/addon-sdk"
|
|
19
20
|
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"jchat-addon": "./dist/cli.mjs"
|
|
23
|
+
},
|
|
20
24
|
"files": [
|
|
21
25
|
"dist",
|
|
26
|
+
"tsconfig.addon.json",
|
|
22
27
|
"README.md",
|
|
23
28
|
"CHANGELOG.md"
|
|
24
29
|
],
|
|
@@ -30,6 +35,10 @@
|
|
|
30
35
|
"types": "./dist/index.d.mts",
|
|
31
36
|
"import": "./dist/index.mjs"
|
|
32
37
|
},
|
|
38
|
+
"./cli": {
|
|
39
|
+
"types": "./dist/cli.d.mts",
|
|
40
|
+
"import": "./dist/cli.mjs"
|
|
41
|
+
},
|
|
33
42
|
"./diagnostics": {
|
|
34
43
|
"types": "./dist/diagnostics.d.mts",
|
|
35
44
|
"import": "./dist/diagnostics.mjs"
|
|
@@ -37,7 +46,17 @@
|
|
|
37
46
|
"./vite": {
|
|
38
47
|
"types": "./dist/vite.d.mts",
|
|
39
48
|
"import": "./dist/vite.mjs"
|
|
40
|
-
}
|
|
49
|
+
},
|
|
50
|
+
"./ui": {
|
|
51
|
+
"types": "./dist/ui.d.mts",
|
|
52
|
+
"import": "./dist/ui.mjs"
|
|
53
|
+
},
|
|
54
|
+
"./ui/tailwind.css": {
|
|
55
|
+
"style": "./src/tailwind.css",
|
|
56
|
+
"import": "./src/tailwind.css",
|
|
57
|
+
"default": "./src/tailwind.css"
|
|
58
|
+
},
|
|
59
|
+
"./tsconfig.json": "./tsconfig.addon.json"
|
|
41
60
|
},
|
|
42
61
|
"publishConfig": {
|
|
43
62
|
"access": "public"
|
|
@@ -49,8 +68,13 @@
|
|
|
49
68
|
"typecheck": "tsc --noEmit",
|
|
50
69
|
"prepack": "bun run build"
|
|
51
70
|
},
|
|
71
|
+
"dependencies": {},
|
|
52
72
|
"devDependencies": {
|
|
53
73
|
"@jchat/icon": "workspace:*",
|
|
74
|
+
"@jchat/ui": "workspace:*",
|
|
75
|
+
"@tailwindcss/vite": "catalog:",
|
|
76
|
+
"@tanstack/react-query": "catalog:",
|
|
77
|
+
"@types/bun": "catalog:",
|
|
54
78
|
"@types/react": "catalog:",
|
|
55
79
|
"elysia": "catalog:",
|
|
56
80
|
"kysely": "^catalog:",
|
|
@@ -58,6 +82,8 @@
|
|
|
58
82
|
"vite": "catalog:"
|
|
59
83
|
},
|
|
60
84
|
"peerDependencies": {
|
|
85
|
+
"@tailwindcss/vite": "catalog:",
|
|
86
|
+
"@tanstack/react-query": "catalog:",
|
|
61
87
|
"elysia": "catalog:",
|
|
62
88
|
"kysely": "^catalog:",
|
|
63
89
|
"react": "catalog:",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"display": "JChat Addon Base",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"moduleResolution": "bundler",
|
|
8
|
+
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
|
9
|
+
"jsx": "react-jsx",
|
|
10
|
+
"strict": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"verbatimModuleSyntax": true,
|
|
13
|
+
"resolveJsonModule": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"types": ["bun", "vite/client"]
|
|
18
|
+
},
|
|
19
|
+
"exclude": ["build", "dist", "node_modules"]
|
|
20
|
+
}
|