@jchat/create-addon 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 CHANGED
@@ -1,5 +1,12 @@
1
1
  # @jchat/create-addon
2
2
 
3
+ ## 1.0.0-alpha.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 8b8297f: Rename package from `create-jchat-addon` to `@jchat/create-addon` and update binary script to `create-addon`.
8
+ - 5bbb2b6: Inherit jchatVersion and addonSdkVersion directly from @jchat/create-addon package version when generating standalone devkit.
9
+
3
10
  ## 1.0.0-alpha.3
4
11
 
5
12
  ## 1.0.0-alpha.2
package/README.md CHANGED
@@ -14,7 +14,7 @@ bunx @jchat/create-addon <addon-id>
14
14
 
15
15
  - `<addon-id>`: (Required) The unique ID for your addon, typically hyphenated (e.g., `weather-addon`).
16
16
  - `--target=<directory>`: (Optional) The directory to generate the workspace in. Defaults to `../<addon-id>` relative to the current working directory.
17
- - `--image=<image>`: (Optional) A specific Docker image to use for the sandbox environment. Defaults to `ghcr.io/mjjabarullah/addon-developer-sandbox`.
17
+ - `--image=<image>`: (Optional) A specific Docker / Podman container image to use for the sandbox environment. Defaults to `ghcr.io/mjjabarullah/addon-developer-sandbox`.
18
18
 
19
19
  ### Example
20
20
 
@@ -26,7 +26,7 @@ cd my-addon
26
26
  ## Requirements
27
27
 
28
28
  - Bun 1.3+
29
- - Docker
29
+ - Docker or Podman
30
30
 
31
31
  ## Licensing
32
32
 
package/dist/cli.mjs CHANGED
@@ -18,9 +18,9 @@ async function runCreator(arguments_) {
18
18
  const options = parseCreatorArguments(arguments_);
19
19
  writeStandaloneDevkit({
20
20
  ...options,
21
- jchatVersion: manifest.jchat.jchatVersion,
22
- addonSdkVersion: manifest.jchat.addonSdkVersion,
23
- sandboxImage: options.sandboxImage ?? `${manifest.jchat.sandboxImage}:${manifest.jchat.jchatVersion.replaceAll("+", "-")}`
21
+ jchatVersion: manifest.version,
22
+ addonSdkVersion: manifest.version,
23
+ sandboxImage: options.sandboxImage ?? `${manifest.jchat?.sandboxImage ?? "ghcr.io/mjjabarullah/addon-developer-sandbox"}:${manifest.version.replaceAll("+", "-")}`
24
24
  });
25
25
  return path.resolve(options.targetDir);
26
26
  }
@@ -1,6 +1,19 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  //#region ../addon-sdk/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);
@@ -98,7 +111,7 @@ function createComposeFile() {
98
111
  ports:
99
112
  - "127.0.0.1:\${JCHAT_SANDBOX_PORT:-4317}:4317"
100
113
  volumes:
101
- - ./addon:/app/addons-dev/\${JCHAT_SANDBOX_ADDON_ID:?Set addon id}:ro
114
+ - ./addon:/app/addons/\${JCHAT_SANDBOX_ADDON_ID:?Set addon id}:ro
102
115
  - sandbox_uploads:/app/uploads
103
116
  depends_on:
104
117
  db:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jchat/create-addon",
3
- "version": "1.0.0-alpha.3",
3
+ "version": "1.0.0-alpha.4",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "addon",
@@ -22,7 +22,6 @@
22
22
  },
23
23
  "files": [
24
24
  "dist",
25
- "src",
26
25
  "README.md",
27
26
  "CHANGELOG.md"
28
27
  ],
@@ -40,23 +39,21 @@
40
39
  },
41
40
  "scripts": {
42
41
  "build": "tsdown",
43
- "lint": "oxlint . --config=../../oxlint.json",
42
+ "lint": "oxlint .",
44
43
  "format": "oxfmt . --write",
45
44
  "typecheck": "tsc --noEmit",
46
45
  "prepack": "bun run build"
47
46
  },
48
47
  "devDependencies": {
49
- "@jchat/addon-sdk": "1.0.0-alpha.3",
50
- "@types/node": "^26.1.2",
51
- "bun-types": "^1.3.14",
48
+ "@jchat/addon-sdk": "workspace:*",
49
+ "@types/node": "catalog:",
50
+ "bun-types": "catalog:",
52
51
  "tsdown": "^0.22.14"
53
52
  },
54
53
  "engines": {
55
54
  "bun": ">=1.3.11"
56
55
  },
57
56
  "jchat": {
58
- "jchatVersion": "1.0.0-alpha.0",
59
- "addonSdkVersion": "0.0.1",
60
57
  "sandboxImage": "ghcr.io/mjjabarullah/addon-developer-sandbox"
61
58
  }
62
59
  }
package/src/cli.test.ts DELETED
@@ -1,30 +0,0 @@
1
- import { describe, expect, test } from "bun:test"
2
- import { parseCreatorArguments } from "./cli"
3
-
4
- describe("create-addon CLI", () => {
5
- test("uses the addon id as the default target", () => {
6
- expect(parseCreatorArguments(["weather-addon"])).toEqual({
7
- addonId: "weather-addon",
8
- targetDir: "weather-addon",
9
- sandboxImage: undefined
10
- })
11
- })
12
-
13
- test("accepts target and image overrides", () => {
14
- expect(
15
- parseCreatorArguments([
16
- "weather-addon",
17
- "--target=../weather-kit",
18
- "--image=registry.example/sandbox:test"
19
- ])
20
- ).toEqual({
21
- addonId: "weather-addon",
22
- targetDir: "../weather-kit",
23
- sandboxImage: "registry.example/sandbox:test"
24
- })
25
- })
26
-
27
- test("requires an addon id", () => {
28
- expect(() => parseCreatorArguments([])).toThrow("Usage: bunx @jchat/create-addon")
29
- })
30
- })
package/src/cli.ts DELETED
@@ -1,55 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import * as path from "node:path"
4
- import { writeStandaloneDevkit } from "./generator"
5
-
6
- interface CreatorPackageManifest {
7
- version: string
8
- jchat: {
9
- jchatVersion: string
10
- addonSdkVersion: string
11
- sandboxImage: string
12
- }
13
- }
14
-
15
- export interface CreatorArguments {
16
- addonId: string
17
- targetDir: string
18
- sandboxImage?: string
19
- }
20
-
21
- export function parseCreatorArguments(arguments_: readonly string[]): CreatorArguments {
22
- const positional = arguments_.filter((argument) => !argument.startsWith("--"))
23
- const addonId = positional[0]
24
- if (addonId === undefined || addonId.startsWith("-")) {
25
- throw new Error("Usage: bunx @jchat/create-addon <addon-id> [--target=<directory>] [--image=<image>]")
26
- }
27
- const targetArgument = arguments_.find((argument) => argument.startsWith("--target="))
28
- const imageArgument = arguments_.find((argument) => argument.startsWith("--image="))
29
- return {
30
- addonId,
31
- targetDir: targetArgument?.slice("--target=".length) || addonId,
32
- sandboxImage: imageArgument?.slice("--image=".length) || undefined
33
- }
34
- }
35
-
36
- export async function runCreator(arguments_: readonly string[]): Promise<string> {
37
- const manifest = (await Bun.file(
38
- new URL("../package.json", import.meta.url)
39
- ).json()) as CreatorPackageManifest
40
- const options = parseCreatorArguments(arguments_)
41
- writeStandaloneDevkit({
42
- ...options,
43
- jchatVersion: manifest.jchat.jchatVersion,
44
- addonSdkVersion: manifest.jchat.addonSdkVersion,
45
- sandboxImage:
46
- options.sandboxImage ??
47
- `${manifest.jchat.sandboxImage}:${manifest.jchat.jchatVersion.replaceAll("+", "-")}`
48
- })
49
- return path.resolve(options.targetDir)
50
- }
51
-
52
- if (import.meta.main) {
53
- const target = await runCreator(process.argv.slice(2))
54
- console.log(`Created standalone addon development kit at ${target}`)
55
- }
package/src/generator.ts DELETED
@@ -1,428 +0,0 @@
1
- import type { AddonManifest } from "@jchat/addon-sdk"
2
- import { createCompatibleMajorRange } from "@jchat/addon-sdk/diagnostics"
3
- import * as fs from "node:fs"
4
- import * as path from "node:path"
5
-
6
- export interface StandaloneDevkitOptions {
7
- addonId: string
8
- targetDir: string
9
- jchatVersion: string
10
- addonSdkVersion: string
11
- sandboxImage?: string
12
- }
13
-
14
- const ADDON_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/
15
- const DEFAULT_SANDBOX_IMAGE = "ghcr.io/mjjabarullah/addon-developer-sandbox"
16
-
17
- export function createStandaloneDevkitFiles(
18
- options: StandaloneDevkitOptions
19
- ): Readonly<Record<string, string>> {
20
- if (!ADDON_ID_PATTERN.test(options.addonId)) {
21
- throw new Error("Addon id must contain lowercase letters, numbers, and hyphens")
22
- }
23
- const image =
24
- options.sandboxImage ?? `${DEFAULT_SANDBOX_IMAGE}:${options.jchatVersion.replace(/\+/g, "-")}`
25
- const manifest: AddonManifest = {
26
- id: options.addonId,
27
- name: toDisplayName(options.addonId),
28
- version: "1.0.0",
29
- description: `${toDisplayName(options.addonId)} addon for JChat`,
30
- author: "Developer",
31
- compatibility: {
32
- jchat: createCompatibleMajorRange(options.jchatVersion),
33
- addonSdk: createCompatibleMajorRange(options.addonSdkVersion)
34
- },
35
- frontend: {
36
- bundle: "./ui.js",
37
- mountPoints: ["chat-toolbar"]
38
- },
39
- permissions: []
40
- }
41
-
42
- return Object.freeze({
43
- ".env.example": createEnvironmentFile(options.addonId, image),
44
- ".gitignore": ["node_modules/", "addon/node_modules/", "addon/build/", ".env", ""].join("\n"),
45
- "README.md": createReadme(options.addonId),
46
- "docker-compose.yml": createComposeFile(),
47
- "package.json": `${JSON.stringify(createRootPackage(options.addonId), null, 2)}\n`,
48
- "scripts/devkit.ts": createLifecycleScript(),
49
- "addon/package.json": `${JSON.stringify(
50
- createAddonPackage(options.addonId, options.addonSdkVersion),
51
- null,
52
- 2
53
- )}\n`,
54
- "addon/tsconfig.json": `${JSON.stringify(createTsConfig(), null, 2)}\n`,
55
- "addon/vite.config.ts": createViteConfig(),
56
- "addon/src/manifest.ts": createManifestSource(manifest),
57
- "addon/src/tailwind.css": createTailwindSource(),
58
- "addon/src/ui.tsx": createUiSource(manifest.name)
59
- })
60
- }
61
-
62
- export function writeStandaloneDevkit(options: StandaloneDevkitOptions): void {
63
- const targetDir = path.resolve(options.targetDir)
64
- if (fs.existsSync(targetDir)) {
65
- throw new Error(`Development kit target already exists: ${targetDir}`)
66
- }
67
-
68
- for (const [relativePath, contents] of Object.entries(createStandaloneDevkitFiles(options))) {
69
- const target = path.join(targetDir, ...relativePath.split("/"))
70
- fs.mkdirSync(path.dirname(target), { recursive: true })
71
- fs.writeFileSync(target, contents)
72
- }
73
- }
74
-
75
- function createEnvironmentFile(addonId: string, image: string): string {
76
- return [
77
- `JCHAT_SANDBOX_IMAGE=${image}`,
78
- `JCHAT_SANDBOX_ADDON_ID=${addonId}`,
79
- "JCHAT_SANDBOX_PORT=4317",
80
- "JCHAT_SANDBOX_HTTP_MOCK_PORT=4318",
81
- "JCHAT_SANDBOX_HTTP_MOCK_OFFLINE=false",
82
- "JCHAT_SANDBOX_ADDON_HTTP_MOCK_URL=http://http-mock:4318",
83
- ""
84
- ].join("\n")
85
- }
86
-
87
- function createComposeFile(): string {
88
- return `services:
89
- sandbox:
90
- image: \${JCHAT_SANDBOX_IMAGE:?Copy .env.example to .env}
91
- restart: unless-stopped
92
- environment:
93
- NODE_ENV: development
94
- JCHAT_PORT: "4317"
95
- JCHAT_COOKIE_SECRET: addon-sandbox-cookie-secret
96
- JCHAT_DATABASE_URL: postgresql://jchat:jchat@db:5432/jchat
97
- JCHAT_REDIS_DATABASE_URL: redis://redis:6379
98
- JCHAT_STORAGE_TYPE: LOCAL
99
- JCHAT_BOT_NAME: Sandbox Bot
100
- JCHAT_BOT_EMAIL: bot@sandbox.local
101
- JCHAT_DOMAIN: localhost
102
- JCHAT_SITE_URL: http://localhost:\${JCHAT_SANDBOX_PORT:-4317}
103
- JCHAT_ROUTING_MODE: path
104
- JCHAT_ADDON_ENCRYPTION_KEY: addon-sandbox-encryption-key
105
- JCHAT_ADDON_HTTP_MOCK_URL: \${JCHAT_SANDBOX_ADDON_HTTP_MOCK_URL-http://http-mock:4318}
106
- ports:
107
- - "127.0.0.1:\${JCHAT_SANDBOX_PORT:-4317}:4317"
108
- volumes:
109
- - ./addon:/app/addons-dev/\${JCHAT_SANDBOX_ADDON_ID:?Set addon id}:ro
110
- - sandbox_uploads:/app/uploads
111
- depends_on:
112
- db:
113
- condition: service_healthy
114
- redis:
115
- condition: service_healthy
116
- http-mock:
117
- condition: service_healthy
118
-
119
- http-mock:
120
- image: \${JCHAT_SANDBOX_IMAGE:?Copy .env.example to .env}
121
- entrypoint: ["/app/addon-http-mock"]
122
- environment:
123
- JCHAT_SANDBOX_HTTP_MOCK_PORT: "4318"
124
- JCHAT_SANDBOX_HTTP_MOCK_OFFLINE: \${JCHAT_SANDBOX_HTTP_MOCK_OFFLINE:-false}
125
- ports:
126
- - "127.0.0.1:\${JCHAT_SANDBOX_HTTP_MOCK_PORT:-4318}:4318"
127
- healthcheck:
128
- test: ["CMD", "/app/addon-http-mock", "--healthcheck"]
129
- interval: 2s
130
- timeout: 3s
131
- retries: 30
132
-
133
- db:
134
- image: postgres:18-alpine
135
- environment:
136
- POSTGRES_USER: jchat
137
- POSTGRES_PASSWORD: jchat
138
- POSTGRES_DB: jchat
139
- volumes:
140
- - sandbox_postgres:/var/lib/postgresql/data
141
- healthcheck:
142
- test: ["CMD-SHELL", "pg_isready -U jchat"]
143
- interval: 2s
144
- timeout: 3s
145
- retries: 30
146
-
147
- redis:
148
- image: redis:8.0.6-alpine3.21
149
- volumes:
150
- - sandbox_redis:/data
151
- healthcheck:
152
- test: ["CMD", "redis-cli", "ping"]
153
- interval: 2s
154
- timeout: 3s
155
- retries: 30
156
-
157
- volumes:
158
- sandbox_postgres:
159
- sandbox_redis:
160
- sandbox_uploads:
161
- `
162
- }
163
-
164
- function createRootPackage(addonId: string) {
165
- return {
166
- name: `${addonId}-development-kit`,
167
- private: true,
168
- type: "module",
169
- workspaces: ["addon"],
170
- scripts: {
171
- sandbox: "bun run ./scripts/devkit.ts run",
172
- "sandbox:test": "bun run ./scripts/devkit.ts test",
173
- "sandbox:reset": "bun run ./scripts/devkit.ts reset",
174
- "sandbox:package": "bun run ./scripts/devkit.ts package",
175
- "sandbox:cleanup": "bun run ./scripts/devkit.ts cleanup"
176
- },
177
- devDependencies: {
178
- "bun-types": "^1.3.14"
179
- },
180
- engines: {
181
- bun: ">=1.3.11"
182
- }
183
- }
184
- }
185
-
186
- function createAddonPackage(addonId: string, addonSdkVersion: string) {
187
- return {
188
- name: `@jchat/${addonId}`,
189
- version: "1.0.0",
190
- private: true,
191
- type: "module",
192
- scripts: {
193
- dev: "vite build --watch --mode=development",
194
- build: "vite build --mode=production",
195
- test: "bun test",
196
- typecheck: "tsc --noEmit"
197
- },
198
- dependencies: {
199
- "@jchat/addon-sdk": `^${addonSdkVersion}`,
200
- "@tanstack/react-query": "^5.101.4",
201
- react: "^19.2.8",
202
- "react-dom": "^19.2.8"
203
- },
204
- devDependencies: {
205
- "@tailwindcss/vite": "^4.3.3",
206
- "@types/node": "^26.1.1",
207
- "@types/react": "^19.2.17",
208
- "@types/react-dom": "^19.2.3",
209
- "bun-types": "^1.3.14",
210
- tailwindcss: "^4.3.3",
211
- typescript: "^7.0.2",
212
- vite: "^8.1.5"
213
- }
214
- }
215
- }
216
-
217
- function createTsConfig() {
218
- return {
219
- compilerOptions: {
220
- strict: true,
221
- target: "ESNext",
222
- module: "ESNext",
223
- moduleResolution: "bundler",
224
- jsx: "react-jsx",
225
- noEmit: true,
226
- types: ["bun-types", "node"]
227
- },
228
- include: ["src/**/*.ts", "src/**/*.tsx", "vite.config.ts"]
229
- }
230
- }
231
-
232
- function createManifestSource(manifest: AddonManifest): string {
233
- return `import type { AddonManifest } from "@jchat/addon-sdk"
234
-
235
- const manifest: AddonManifest = ${JSON.stringify(manifest, null, 2)}
236
-
237
- export default manifest
238
- `
239
- }
240
-
241
- function createViteConfig(): string {
242
- return `import { jchatAddon } from "@jchat/addon-sdk/vite"
243
- import tailwindcss from "@tailwindcss/vite"
244
- import path from "node:path"
245
- import { defineConfig } from "vite"
246
- import manifest from "./src/manifest"
247
-
248
- export default defineConfig({
249
- plugins: [tailwindcss(), jchatAddon({ manifest })],
250
- build: {
251
- outDir: "build",
252
- emptyOutDir: true,
253
- lib: {
254
- entry: path.resolve(import.meta.dirname, "src/ui.tsx"),
255
- formats: ["es"],
256
- fileName: () => "ui.[hash].js"
257
- },
258
- rolldownOptions: {
259
- external: [
260
- "react",
261
- "react-dom",
262
- "react/jsx-runtime",
263
- "@tanstack/react-query",
264
- "@jchat/addon-sdk"
265
- ],
266
- output: {
267
- format: "esm"
268
- }
269
- }
270
- }
271
- })
272
- `
273
- }
274
-
275
- function createUiSource(name: string): string {
276
- return `import type { AddonProps } from "@jchat/addon-sdk"
277
- import { useAddonSDK, useIcons } from "@jchat/addon-sdk"
278
- import "./tailwind.css"
279
-
280
- export default function Addon({ mountPoint }: AddonProps) {
281
- const sdk = useAddonSDK()
282
- const { Icons } = useIcons()
283
-
284
- return (
285
- <div className="rounded border border-border bg-card p-2 text-card-foreground">
286
- <div className="mb-2 flex items-center gap-2">
287
- <Icons.Plus aria-hidden="true" className="size-4 text-primary" />
288
- <strong>${name}</strong>
289
- </div>
290
- <p className="mb-2 text-sm text-muted-foreground">Mounted at {mountPoint}</p>
291
- <button
292
- type="button"
293
- className="rounded bg-primary px-3 py-2 text-primary-foreground"
294
- onClick={() => sdk.toast("Hello from ${name}")}
295
- >
296
- Test addon
297
- </button>
298
- </div>
299
- )
300
- }
301
- `
302
- }
303
-
304
- function createTailwindSource(): string {
305
- return `@import "tailwindcss";
306
-
307
- @theme inline {
308
- --color-background: var(--background);
309
- --color-foreground: var(--foreground);
310
- --color-card: var(--card);
311
- --color-card-foreground: var(--card-foreground);
312
- --color-border: var(--border);
313
- --color-primary: var(--primary);
314
- --color-primary-foreground: var(--primary-foreground);
315
- --color-muted-foreground: var(--muted-foreground);
316
- }
317
- `
318
- }
319
-
320
- function createLifecycleScript(): string {
321
- return `import * as fs from "node:fs"
322
- import * as path from "node:path"
323
-
324
- type Command = "run" | "test" | "reset" | "package" | "cleanup"
325
-
326
- const command = (process.argv[2] ?? "run") as Command
327
- if (!["run", "test", "reset", "package", "cleanup"].includes(command)) {
328
- throw new Error(\`Unknown development-kit command: \${command}\`)
329
- }
330
-
331
- const root = path.resolve(import.meta.dir, "..")
332
- const environment = {
333
- ...process.env,
334
- ...readEnvironment(path.join(root, ".env"))
335
- }
336
- const addonId = environment.JCHAT_SANDBOX_ADDON_ID
337
- if (!addonId) throw new Error("JCHAT_SANDBOX_ADDON_ID is missing from .env")
338
- const compose = [
339
- "docker",
340
- "compose",
341
- "--project-name",
342
- \`jchat-addon-devkit-\${addonId}\`,
343
- "--file",
344
- path.join(root, "docker-compose.yml")
345
- ]
346
-
347
- if (command === "test") {
348
- await run(["bun", "test"], path.join(root, "addon"), environment)
349
- } else if (command === "package") {
350
- await run(["bun", "run", "build"], path.join(root, "addon"), environment)
351
- } else if (command === "cleanup") {
352
- await run([...compose, "down", "--remove-orphans", "--volumes"], root, environment)
353
- } else {
354
- if (command === "reset") {
355
- await run([...compose, "down", "--remove-orphans", "--volumes"], root, environment)
356
- }
357
- await run(["bun", "run", "build"], path.join(root, "addon"), environment)
358
- const watcher = Bun.spawn(["bun", "run", "dev"], {
359
- cwd: path.join(root, "addon"),
360
- env: environment,
361
- stdout: "inherit",
362
- stderr: "inherit"
363
- })
364
- try {
365
- await run([...compose, "up"], root, environment)
366
- } finally {
367
- watcher.kill()
368
- await watcher.exited
369
- }
370
- }
371
-
372
- async function run(command: string[], cwd: string, env: Record<string, string | undefined>) {
373
- const child = Bun.spawn(command, { cwd, env, stdin: "inherit", stdout: "inherit", stderr: "inherit" })
374
- const exitCode = await child.exited
375
- if (exitCode !== 0) throw new Error(\`\${command.join(" ")} exited with code \${exitCode}\`)
376
- }
377
-
378
- function readEnvironment(file: string): Record<string, string> {
379
- if (!fs.existsSync(file)) throw new Error("Copy .env.example to .env before running the kit")
380
- return Object.fromEntries(
381
- fs.readFileSync(file, "utf8")
382
- .split(/\\r?\\n/)
383
- .filter((line) => line && !line.startsWith("#"))
384
- .map((line) => {
385
- const separator = line.indexOf("=")
386
- return [line.slice(0, separator), line.slice(separator + 1)]
387
- })
388
- )
389
- }
390
- `
391
- }
392
-
393
- function createReadme(addonId: string): string {
394
- return `# ${toDisplayName(addonId)} Development Kit
395
-
396
- This workspace develops \`${addonId}\` against the license-free JChat developer sandbox without
397
- including JChat Core source.
398
-
399
- ## Start
400
-
401
- \`\`\`powershell
402
- Copy-Item .env.example .env
403
- bun install
404
- bun sandbox
405
- \`\`\`
406
-
407
- Open \`http://127.0.0.1:4317\`. The HTTP fixture recorder is available at
408
- \`http://127.0.0.1:4318/requests\`.
409
-
410
- ## Commands
411
-
412
- - \`bun sandbox\`
413
- - \`bun sandbox:test\`
414
- - \`bun sandbox:reset\`
415
- - \`bun sandbox:package\`
416
- - \`bun sandbox:cleanup\`
417
-
418
- The referenced JChat packages and sandbox image must be published before this standalone kit can
419
- install or start outside the JChat repository.
420
- `
421
- }
422
-
423
- function toDisplayName(addonId: string): string {
424
- return addonId
425
- .split("-")
426
- .map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`)
427
- .join(" ")
428
- }
package/src/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export {
2
- createStandaloneDevkitFiles,
3
- writeStandaloneDevkit,
4
- type StandaloneDevkitOptions
5
- } from "./generator"