pulumi-package-docs 0.5.0 → 0.7.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
@@ -22,6 +22,21 @@ pulumi-package-docs [options]
22
22
 
23
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.
24
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
+
34
+ On macOS or Linux, it's also available via Homebrew:
35
+
36
+ ```bash
37
+ brew install pierskarsenbarg/tap/pulumi-package-docs
38
+ ```
39
+
25
40
  ## MCP
26
41
 
27
42
  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:
@@ -58,4 +73,9 @@ Build the production app with:
58
73
  npm run build
59
74
  ```
60
75
 
61
- `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`.
76
+ `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:
77
+
78
+ ```bash
79
+ npm run build
80
+ npm run compile:bun
81
+ ```
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,52 @@
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
+ const child = spawn(command[0], command.slice(1), {
24
+ stdio: 'ignore',
25
+ detached: true,
26
+ })
27
+ child.on('error', (err) => {
28
+ console.error(`Could not open browser: ${err.message}`)
29
+ })
30
+ child.unref()
31
+ }
32
+
33
+ console.log(`Serving provider docs for: ${options.dir}`)
34
+
35
+ const bunServer = Bun.serve({
36
+ port: Number(options.port),
37
+ hostname: options.host ? '0.0.0.0' : undefined,
38
+ async fetch(request) {
39
+ const url = new URL(request.url)
40
+ const embeddedPath = embeddedAssets[url.pathname]
41
+ if (embeddedPath) {
42
+ return new Response(Bun.file(embeddedPath))
43
+ }
44
+ return server.fetch(request)
45
+ },
46
+ })
47
+
48
+ const localUrl = `http://localhost:${bunServer.port}/`
49
+ console.log(` ➜ Local: ${localUrl}`)
50
+ console.log(` ➜ MCP: ${new URL('mcp', localUrl)}`)
51
+
52
+ if (options.open) openBrowser(localUrl)
package/bin/cli.js CHANGED
@@ -4,44 +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, open: 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 === '--open') {
22
- options.open = true
23
- } else if (arg === '--help' || arg === '-h') {
24
- options.help = true
25
- }
26
- }
27
- return options
28
- }
29
-
30
- function printHelp() {
31
- console.log(`pulumi-package-docs [options]
32
-
33
- Serves local documentation for the parameterized/local Pulumi providers used
34
- by a Pulumi project.
35
-
36
- Options:
37
- -d, --dir <path> Pulumi project directory to inspect (default: current directory)
38
- -p, --port <port> Port to serve on (default: 3000)
39
- --host Expose the server on your network
40
- --open Open the docs in your default browser once ready
41
- -h, --help Show this help message
42
- `)
43
- }
44
-
45
12
  const options = parseArgs(process.argv.slice(2))
46
13
 
47
14
  if (options.help) {
@@ -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.5.0",
3
+ "version": "0.7.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",