@danxbot/plugin-sdk 0.0.0-stage → 0.1.2

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/cli.js ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.ts
4
+ var USAGE = "usage: danx-plugin publish";
5
+ var [command] = process.argv.slice(2);
6
+ if (command === "publish") {
7
+ process.stderr.write("danx-plugin publish is not available yet: the plugin upload route ships with the next release of this SDK.\n");
8
+ process.exit(1);
9
+ }
10
+ process.stderr.write(`${USAGE}
11
+ `);
12
+ process.exit(command === void 0 ? 0 : 2);
package/dist/vite.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ /** The entry module every plugin build produces; the manifest names it and the app `import()`s it. */
4
+ declare const PLUGIN_ENTRY_FILE = "index.js";
5
+ interface DanxPluginOptions {
6
+ /** The module exporting `CardView` and/or `CardListView`, relative to the project root. */
7
+ readonly entry?: string;
8
+ }
9
+ /**
10
+ * The Vite preset for a 50 Arms card-type plugin: an ES-module library build whose output the app loads with `import()`.
11
+ *
12
+ * - The specifiers in `src/plugins/runtime-contract.ts` (`react`, `react/jsx-runtime`, `react-dom`, `@danxbot/ui`, the card kit) stay
13
+ * EXTERNAL: the page's import map answers them with the app's own modules, so the plugin shares its single React and design system.
14
+ * - Anything else is bundled. Bundling a copy of a shared package (`react-dom/client` or `react-router` are not in the contract) would run a second copy
15
+ * beside the app's, so that fails the build instead of shipping.
16
+ * - Code-split chunks load by relative import from the entry's folder; CSS is emitted as one `index.css`.
17
+ * - `danx-plugin.json` is written beside the output: every file's size and sha256, the entry, the stylesheets and the runtime majors.
18
+ */
19
+ declare function danxPlugin(options?: DanxPluginOptions): Plugin;
20
+
21
+ export { PLUGIN_ENTRY_FILE, danxPlugin };
22
+ export type { DanxPluginOptions };
package/dist/vite.js ADDED
@@ -0,0 +1,119 @@
1
+ // ../../src/plugins/runtime-contract.ts
2
+ var CARD_KIT_MAJOR = 1;
3
+ var CARD_KIT_LIBRARY = "@danxbot/card-kit";
4
+ var PLUGIN_RUNTIME_LIBRARIES = [
5
+ { name: "react", major: 19 },
6
+ { name: "react-dom", major: 19 },
7
+ { name: "@danxbot/ui", major: 26 },
8
+ { name: CARD_KIT_LIBRARY, major: CARD_KIT_MAJOR }
9
+ ];
10
+ var PLUGIN_RUNTIME_SPECIFIERS = [
11
+ { specifier: "react", library: "react" },
12
+ { specifier: "react/jsx-runtime", library: "react" },
13
+ { specifier: "react-dom", library: "react-dom" },
14
+ { specifier: "@danxbot/ui", library: "@danxbot/ui" },
15
+ { specifier: `${CARD_KIT_LIBRARY}@${CARD_KIT_MAJOR}`, library: CARD_KIT_LIBRARY }
16
+ ];
17
+ var PLUGIN_NEVER_BUNDLED_PACKAGES = [
18
+ ...PLUGIN_RUNTIME_LIBRARIES.map((library) => library.name).filter((name) => name !== CARD_KIT_LIBRARY),
19
+ "scheduler",
20
+ "react-router"
21
+ ];
22
+ function pluginRuntimeContract() {
23
+ return {
24
+ specifiers: PLUGIN_RUNTIME_SPECIFIERS.map((entry) => entry.specifier),
25
+ majors: Object.fromEntries(PLUGIN_RUNTIME_LIBRARIES.map((library) => [library.name, library.major]))
26
+ };
27
+ }
28
+
29
+ // src/manifest.ts
30
+ import { createHash } from "node:crypto";
31
+ import { readdirSync, readFileSync, writeFileSync } from "node:fs";
32
+ import { join, relative, sep } from "node:path";
33
+
34
+ // ../../src/plugins/plugin-manifest.ts
35
+ var PLUGIN_MANIFEST_FILE = "danx-plugin.json";
36
+
37
+ // src/manifest.ts
38
+ function filesUnder(root, dir = root) {
39
+ return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => entry.isDirectory() ? filesUnder(root, join(dir, entry.name)) : [join(dir, entry.name)]).sort();
40
+ }
41
+ function describeFile(root, file) {
42
+ const bytes = readFileSync(file);
43
+ return {
44
+ path: relative(root, file).split(sep).join("/"),
45
+ size: bytes.length,
46
+ sha256: createHash("sha256").update(bytes).digest("hex")
47
+ };
48
+ }
49
+ function buildManifest(outDir, entry) {
50
+ const files = filesUnder(outDir).map((file) => describeFile(outDir, file)).filter((file) => file.path !== PLUGIN_MANIFEST_FILE);
51
+ if (!files.some((file) => file.path === entry)) throw new Error(`danx-plugin: the build produced no entry module ${entry} in ${outDir}`);
52
+ return {
53
+ entry,
54
+ styles: files.filter((file) => file.path.endsWith(".css")).map((file) => file.path),
55
+ runtime: pluginRuntimeContract().majors,
56
+ files
57
+ };
58
+ }
59
+ function writeManifest(outDir, entry) {
60
+ const manifest = buildManifest(outDir, entry);
61
+ writeFileSync(join(outDir, PLUGIN_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
62
+ `);
63
+ return manifest;
64
+ }
65
+
66
+ // src/vite.ts
67
+ var PLUGIN_ENTRY_FILE = "index.js";
68
+ var STYLESHEET_FILE = "index.css";
69
+ function bundledNeverPackage(moduleId) {
70
+ const normalised = moduleId.replaceAll("\\", "/");
71
+ return PLUGIN_NEVER_BUNDLED_PACKAGES.find((name) => normalised.includes(`/node_modules/${name}/`));
72
+ }
73
+ function danxPlugin(options = {}) {
74
+ const entry = options.entry ?? "src/index.tsx";
75
+ return {
76
+ name: "danx-plugin",
77
+ config() {
78
+ return {
79
+ // The runtime-contract specifiers include `react/jsx-runtime`, never `react/jsx-dev-runtime`.
80
+ esbuild: { jsx: "automatic", jsxDev: false },
81
+ // Library mode leaves `process.env.NODE_ENV` for the consumer; a browser has no `process`.
82
+ define: { "process.env.NODE_ENV": JSON.stringify("production") },
83
+ build: {
84
+ target: "es2022",
85
+ sourcemap: true,
86
+ cssCodeSplit: false,
87
+ lib: { entry, formats: ["es"], fileName: () => PLUGIN_ENTRY_FILE },
88
+ rollupOptions: {
89
+ external: PLUGIN_RUNTIME_SPECIFIERS.map((shared) => shared.specifier),
90
+ output: {
91
+ chunkFileNames: "chunks/[name]-[hash].js",
92
+ assetFileNames: (asset) => asset.names.some((name) => name.endsWith(".css")) ? STYLESHEET_FILE : "assets/[name]-[hash][extname]"
93
+ }
94
+ }
95
+ }
96
+ };
97
+ },
98
+ generateBundle(_options, bundle) {
99
+ for (const output of Object.values(bundle)) {
100
+ if (output.type !== "chunk") continue;
101
+ for (const id of output.moduleIds) {
102
+ const duplicate = bundledNeverPackage(id);
103
+ if (duplicate === void 0) continue;
104
+ throw new Error(
105
+ `danx-plugin: ${output.fileName} would bundle a copy of ${duplicate}, which the app already serves (${id}). Import only the specifiers the runtime contract lists (${PLUGIN_RUNTIME_SPECIFIERS.map((shared) => shared.specifier).join(", ")}); the card kit also re-exports Link and useNavigate in place of react-router.`
106
+ );
107
+ }
108
+ }
109
+ },
110
+ writeBundle(options2) {
111
+ if (options2.dir === void 0) throw new Error("danx-plugin: the build has no output directory to write the manifest into");
112
+ writeManifest(options2.dir, PLUGIN_ENTRY_FILE);
113
+ }
114
+ };
115
+ }
116
+ export {
117
+ PLUGIN_ENTRY_FILE,
118
+ danxPlugin
119
+ };
package/package.json CHANGED
@@ -1,6 +1,57 @@
1
1
  {
2
2
  "name": "@danxbot/plugin-sdk",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.2",
4
+ "description": "SDK for building 50 Arms card-type plugins (DX-5170): the card kit's type declarations, a Vite preset that builds a plugin against the app's shared runtime and writes its manifest, and the danx-plugin CLI.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "danx-plugin": "dist/cli.js"
9
+ },
10
+ "exports": {
11
+ "./vite": {
12
+ "types": "./dist/vite.d.ts",
13
+ "default": "./dist/vite.js"
14
+ },
15
+ "./card-kit": {
16
+ "types": "./dist/card-kit.d.ts"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/newms87/danxbot.git",
26
+ "directory": "packages/danx-plugin-sdk"
27
+ },
28
+ "engines": {
29
+ "node": ">=20"
30
+ },
31
+ "peerDependencies": {
32
+ "@danxbot/ui": "^26.0.0",
33
+ "@types/react": "^19.0.0",
34
+ "react": "^19.0.0",
35
+ "react-router": "^7.0.0",
36
+ "vite": "^7.1.9"
37
+ },
38
+ "scripts": {
39
+ "prepublishOnly": "bash ../../scripts/assert-tree-contains-origin-main.sh @danxbot/plugin-sdk",
40
+ "build": "node scripts/build.mjs",
41
+ "typecheck": "tsc -p tsconfig.test.json --noEmit",
42
+ "test": "vitest run"
43
+ },
44
+ "devDependencies": {
45
+ "@danxbot/ui": "26.7.1",
46
+ "@types/node": "^22.0.0",
47
+ "@types/react": "^19.2.2",
48
+ "esbuild": "^0.25.0",
49
+ "react": "^19.2.0",
50
+ "react-router": "^7.18.2",
51
+ "rollup": "^4.52.0",
52
+ "rollup-plugin-dts": "^6.2.0",
53
+ "typescript": "^5.9.3",
54
+ "vite": "^7.1.9",
55
+ "vitest": "^4.1.11"
56
+ }
57
+ }