pulumi-package-docs 0.4.0 → 0.6.0

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/README.md CHANGED
@@ -16,11 +16,21 @@ pulumi-package-docs [options]
16
16
  -d, --dir <path> Pulumi project directory to inspect (default: current directory)
17
17
  -p, --port <port> Port to serve on (default: 3000)
18
18
  --host Expose the server on your network
19
+ --open Open the docs in your default browser once ready
19
20
  -h, --help Show this help message
20
21
  ```
21
22
 
22
23
  Requires the `pulumi` CLI to be installed and on `PATH`; it's used to fetch each provider's schema (`pulumi package get-schema`). If a schema was fetched successfully before, it's cached and reused if a later CLI call fails.
23
24
 
25
+ ### Standalone binary
26
+
27
+ Each [release](https://github.com/pierskarsenbarg/pulumi-package-docs/releases) also includes standalone executables (macOS arm64/x64, Linux x64/arm64, Windows x64) built with Bun — no Node.js install required. Download the one for your platform, make it executable, and run it the same way:
28
+
29
+ ```bash
30
+ chmod +x pulumi-package-docs-darwin-arm64
31
+ ./pulumi-package-docs-darwin-arm64 --dir /path/to/pulumi/project
32
+ ```
33
+
24
34
  ## MCP
25
35
 
26
36
  The server also exposes an [MCP](https://modelcontextprotocol.io) endpoint at `/mcp` (Streamable HTTP), so a coding agent can look up the same local provider docs without browsing the site. Point an MCP client at `http://localhost:3000/mcp` (e.g. in Claude Code, `claude mcp add --transport http pulumi-package-docs http://localhost:3000/mcp`). Tools:
@@ -57,4 +67,9 @@ Build the production app with:
57
67
  npm run build
58
68
  ```
59
69
 
60
- `bin/cli.js` is the `npx` entry point: it serves the production build with `vite preview` if one exists (`npm run build` first), otherwise falls back to `vite dev`.
70
+ `bin/cli.js` is the `npx` entry point: it serves the production build with `vite preview` if one exists (`npm run build` first), otherwise falls back to `vite dev`. `bin/cli-bun.js` is a separate entry point used to build the standalone Bun executables (see above); it serves the built SSR handler directly with `Bun.serve` instead of shelling out to Vite. Build one locally with:
71
+
72
+ ```bash
73
+ npm run build
74
+ npm run compile:bun
75
+ ```
package/bin/args.js ADDED
@@ -0,0 +1,35 @@
1
+ import { resolve } from 'node:path'
2
+
3
+ export function parseArgs(argv) {
4
+ const options = { dir: process.cwd(), port: '3000', host: false, open: false }
5
+ for (let i = 0; i < argv.length; i++) {
6
+ const arg = argv[i]
7
+ if (arg === '--dir' || arg === '-d') {
8
+ options.dir = resolve(argv[++i])
9
+ } else if (arg === '--port' || arg === '-p') {
10
+ options.port = argv[++i]
11
+ } else if (arg === '--host') {
12
+ options.host = true
13
+ } else if (arg === '--open') {
14
+ options.open = true
15
+ } else if (arg === '--help' || arg === '-h') {
16
+ options.help = true
17
+ }
18
+ }
19
+ return options
20
+ }
21
+
22
+ export function printHelp() {
23
+ console.log(`pulumi-package-docs [options]
24
+
25
+ Serves local documentation for the parameterized/local Pulumi providers used
26
+ by a Pulumi project.
27
+
28
+ Options:
29
+ -d, --dir <path> Pulumi project directory to inspect (default: current directory)
30
+ -p, --port <port> Port to serve on (default: 3000)
31
+ --host Expose the server on your network
32
+ --open Open the docs in your default browser once ready
33
+ -h, --help Show this help message
34
+ `)
35
+ }
package/bin/cli-bun.js ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bun
2
+ import { spawn } from 'node:child_process'
3
+ import { parseArgs, printHelp } from './args.js'
4
+ import server from '../dist/server/server.js'
5
+ import embeddedAssets from './embedded-assets.generated.js'
6
+
7
+ const options = parseArgs(process.argv.slice(2))
8
+
9
+ if (options.help) {
10
+ printHelp()
11
+ process.exit(0)
12
+ }
13
+
14
+ process.env.PULUMI_LOCAL_DOCS_DIR = options.dir
15
+
16
+ function openBrowser(url) {
17
+ const command =
18
+ process.platform === 'darwin'
19
+ ? ['open', url]
20
+ : process.platform === 'win32'
21
+ ? ['cmd', '/c', 'start', '', url]
22
+ : ['xdg-open', url]
23
+ spawn(command[0], command.slice(1), {
24
+ stdio: 'ignore',
25
+ detached: true,
26
+ }).unref()
27
+ }
28
+
29
+ console.log(`Serving provider docs for: ${options.dir}`)
30
+
31
+ const bunServer = Bun.serve({
32
+ port: Number(options.port),
33
+ hostname: options.host ? '0.0.0.0' : undefined,
34
+ async fetch(request) {
35
+ const url = new URL(request.url)
36
+ const embeddedPath = embeddedAssets[url.pathname]
37
+ if (embeddedPath) {
38
+ return new Response(Bun.file(embeddedPath))
39
+ }
40
+ return server.fetch(request)
41
+ },
42
+ })
43
+
44
+ const localUrl = `http://localhost:${bunServer.port}/`
45
+ console.log(` ➜ Local: ${localUrl}`)
46
+ console.log(` ➜ MCP: ${new URL('mcp', localUrl)}`)
47
+
48
+ if (options.open) openBrowser(localUrl)
package/bin/cli.js CHANGED
@@ -4,41 +4,11 @@ import { createRequire } from 'node:module'
4
4
  import { dirname, join, resolve } from 'node:path'
5
5
  import { fileURLToPath } from 'node:url'
6
6
  import { spawn } from 'node:child_process'
7
+ import { parseArgs, printHelp } from './args.js'
7
8
 
8
9
  const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..')
9
10
  const require = createRequire(import.meta.url)
10
11
 
11
- function parseArgs(argv) {
12
- const options = { dir: process.cwd(), port: '3000', host: false }
13
- for (let i = 0; i < argv.length; i++) {
14
- const arg = argv[i]
15
- if (arg === '--dir' || arg === '-d') {
16
- options.dir = resolve(argv[++i])
17
- } else if (arg === '--port' || arg === '-p') {
18
- options.port = argv[++i]
19
- } else if (arg === '--host') {
20
- options.host = true
21
- } else if (arg === '--help' || arg === '-h') {
22
- options.help = true
23
- }
24
- }
25
- return options
26
- }
27
-
28
- function printHelp() {
29
- console.log(`pulumi-package-docs [options]
30
-
31
- Serves local documentation for the parameterized/local Pulumi providers used
32
- by a Pulumi project.
33
-
34
- Options:
35
- -d, --dir <path> Pulumi project directory to inspect (default: current directory)
36
- -p, --port <port> Port to serve on (default: 3000)
37
- --host Expose the server on your network
38
- -h, --help Show this help message
39
- `)
40
- }
41
-
42
12
  const options = parseArgs(process.argv.slice(2))
43
13
 
44
14
  if (options.help) {
@@ -58,6 +28,7 @@ const viteArgs = [
58
28
  options.port,
59
29
  ]
60
30
  if (options.host) viteArgs.push('--host')
31
+ if (options.open) viteArgs.push('--open')
61
32
 
62
33
  if (!hasProductionBuild) {
63
34
  console.log(
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ // Generates bin/embedded-assets.generated.js: a module that statically
3
+ // imports every file under dist/client with `{ type: "file" }`, so `bun
4
+ // build --compile` embeds them into the standalone executable. Must run
5
+ // after `npm run build` (dist/client must exist) and before
6
+ // `bun build --compile ./bin/cli-bun.js`.
7
+ import { readdirSync, statSync, writeFileSync } from 'node:fs'
8
+ import { dirname, join, relative, resolve } from 'node:path'
9
+ import { fileURLToPath } from 'node:url'
10
+
11
+ const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..')
12
+ const clientDir = join(packageRoot, 'dist', 'client')
13
+ const outFile = join(packageRoot, 'bin', 'embedded-assets.generated.js')
14
+
15
+ function walk(dir) {
16
+ const files = []
17
+ for (const entry of readdirSync(dir)) {
18
+ const full = join(dir, entry)
19
+ if (statSync(full).isDirectory()) {
20
+ files.push(...walk(full))
21
+ } else {
22
+ files.push(full)
23
+ }
24
+ }
25
+ return files
26
+ }
27
+
28
+ const files = walk(clientDir)
29
+ const lines = []
30
+ const entries = []
31
+
32
+ files.forEach((file, i) => {
33
+ const urlPath = `/${relative(clientDir, file).split('\\').join('/')}`
34
+ const importPath = `../dist/client/${relative(clientDir, file).split('\\').join('/')}`
35
+ const name = `asset${i}`
36
+ lines.push(
37
+ `import ${name} from ${JSON.stringify(importPath)} with { type: 'file' }`,
38
+ )
39
+ entries.push(` ${JSON.stringify(urlPath)}: ${name},`)
40
+ })
41
+
42
+ const source = `${lines.join('\n')}
43
+
44
+ export default {
45
+ ${entries.join('\n')}
46
+ }
47
+ `
48
+
49
+ writeFileSync(outFile, source)
50
+ console.log(
51
+ `Wrote ${files.length} embedded asset imports to ${relative(packageRoot, outFile)}`,
52
+ )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulumi-package-docs",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Local documentation viewer for the parameterized/local Pulumi providers used by a Pulumi project.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -31,7 +31,7 @@
31
31
  "build": "vite build",
32
32
  "preview": "vite preview",
33
33
  "start": "node bin/cli.js",
34
- "prepublishOnly": "npm run build",
34
+ "compile:bun": "node bin/generate-embedded-assets.js && bun build ./bin/cli-bun.js --compile --outfile pulumi-package-docs",
35
35
  "test": "vitest run",
36
36
  "test:watch": "vitest",
37
37
  "lint": "oxlint",