@useguano/create 0.1.4 → 0.1.5
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/index.js +48 -3
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// The server binds the token to the first admin at /admin setup, and the
|
|
14
14
|
// setup form shows the permissions instead of asking them again.
|
|
15
15
|
import { spawnSync } from 'node:child_process'
|
|
16
|
+
import { createServer } from 'node:net'
|
|
16
17
|
import { existsSync } from 'node:fs'
|
|
17
18
|
import { mkdir, readdir, writeFile } from 'node:fs/promises'
|
|
18
19
|
import { basename, join, resolve } from 'node:path'
|
|
@@ -80,6 +81,38 @@ if ((await readdir(target)).length) {
|
|
|
80
81
|
process.exit(1)
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
/**
|
|
85
|
+
* A free port for THIS project, written into .env as an explicit PORT.
|
|
86
|
+
*
|
|
87
|
+
* Every project used to default to 4174, so a second one on the same machine
|
|
88
|
+
* lost the race and walked to the next free port — which left its MCP entry,
|
|
89
|
+
* the Vite proxy and any open tab addressing the FIRST project's socket, where
|
|
90
|
+
* its own token is unknown and the 401 reads as "the token is dead". An
|
|
91
|
+
* explicit port is a contract the server honours instead of walking, and
|
|
92
|
+
* putting it in a file the user can read makes "which port is this site on" a
|
|
93
|
+
* question with an answer.
|
|
94
|
+
*
|
|
95
|
+
* 4174 is still preferred, so a first project looks exactly as documented.
|
|
96
|
+
*/
|
|
97
|
+
async function pickPort(first = 4174, tries = 40) {
|
|
98
|
+
// A site needs its own port AND the preview port above it, so step by two.
|
|
99
|
+
for (let port = first; port < first + tries * 2; port += 2) {
|
|
100
|
+
if ((await free(port)) && (await free(port + 1))) return port
|
|
101
|
+
}
|
|
102
|
+
return first
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function free(port) {
|
|
106
|
+
return new Promise((resolve) => {
|
|
107
|
+
const probe = createServer()
|
|
108
|
+
probe.once('error', () => resolve(false))
|
|
109
|
+
probe.once('listening', () => probe.close(() => resolve(true)))
|
|
110
|
+
probe.listen(port, '0.0.0.0')
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const port = await pickPort()
|
|
115
|
+
|
|
83
116
|
const files = {
|
|
84
117
|
'package.json':
|
|
85
118
|
JSON.stringify(
|
|
@@ -107,7 +140,16 @@ const files = {
|
|
|
107
140
|
export default {}
|
|
108
141
|
`,
|
|
109
142
|
|
|
110
|
-
|
|
143
|
+
// A real .env, not just the example: the port is this project's identity on
|
|
144
|
+
// the machine, and leaving it to the 4174 default is what makes two projects
|
|
145
|
+
// fight over one address.
|
|
146
|
+
'.env': `# This project's own port. Keep it — two Guano sites on one machine
|
|
147
|
+
# must not share one, or whichever starts first answers for both and the
|
|
148
|
+
# other's MCP token is refused with a 401.
|
|
149
|
+
PORT=${port}
|
|
150
|
+
`,
|
|
151
|
+
|
|
152
|
+
'.env.example': `PORT=${port}
|
|
111
153
|
# GUANO_DATA_DIR=./data # users, media, drafts, the published site — back this up
|
|
112
154
|
# COOKIE_SECURE=1 # set 0 only for plain-HTTP LAN setups
|
|
113
155
|
# PUBLISH_TOKEN= # optional: token for CI publishes
|
|
@@ -128,8 +170,11 @@ A [Guano](https://www.npmjs.com/package/@useguano/guano) site.
|
|
|
128
170
|
npm run dev
|
|
129
171
|
\`\`\`
|
|
130
172
|
|
|
131
|
-
Open http://localhost
|
|
132
|
-
site. Your published site is served at http://localhost
|
|
173
|
+
Open http://localhost:${port}/admin, create the first account, then build your
|
|
174
|
+
site. Your published site is served at http://localhost:${port}/.
|
|
175
|
+
|
|
176
|
+
This project runs on port ${port} (set in \`.env\`). Each Guano site on a
|
|
177
|
+
machine needs its own, so two of them never answer for one address.
|
|
133
178
|
|
|
134
179
|
If you said yes to Claude Desktop when scaffolding, it is already connected:
|
|
135
180
|
the agent token is bound to the admin account you create, and the permissions
|