@aletheia-ios/tools 0.2.0 → 0.2.1

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.
Files changed (2) hide show
  1. package/dist/cli.js +32 -4
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1131,22 +1131,50 @@ function watchRepo(repo) {
1131
1131
  return [watch(repo.packages, { recursive: true }, trigger), watch(repo.lists, { recursive: true }, trigger)];
1132
1132
  }
1133
1133
  /**
1134
+ * Binds the port and reports the one it got, since port 0 picks a free one.
1135
+ *
1136
+ * A busy port is the common way this fails and it arrives as an `error` event rather than a
1137
+ * rejection, so without this it surfaces as an unhandled event and a stack trace.
1138
+ *
1139
+ * @throws `CliError` naming the port when something already holds it.
1140
+ */
1141
+ async function listen(server, port) {
1142
+ try {
1143
+ await new Promise((resolve, reject) => {
1144
+ server.once("error", reject);
1145
+ server.listen(port, "0.0.0.0", () => {
1146
+ server.removeListener("error", reject);
1147
+ resolve();
1148
+ });
1149
+ });
1150
+ } catch (error) {
1151
+ if (error.code === "EADDRINUSE") throw new CliError([`port ${port} is already in use - pass --port <n> to pick another`], { cause: error });
1152
+ throw error;
1153
+ }
1154
+ const address = server.address();
1155
+ return typeof address === "object" && address !== null ? address.port : port;
1156
+ }
1157
+ /**
1134
1158
  * The `serve` command: packs, indexes, serves `dist/` on the lan and rebuilds on change.
1135
1159
  *
1136
1160
  * Binds every interface and prints the lan URL of each list's `index.json`, which is what
1137
1161
  * the app's developer list points at. Port 0 binds a free port. Resolves once listening;
1138
1162
  * the returned `close` stops the watchers and the server.
1139
1163
  *
1140
- * @throws `CliError` when there is no `lists/` directory, before any port is bound.
1164
+ * @throws `CliError` when there is no `lists/` directory, or when the port is taken.
1141
1165
  */
1142
1166
  async function serve(repo, port) {
1143
1167
  const lists = await loadLists(repo);
1144
1168
  await rebuild(repo);
1145
1169
  const server = fileServer(repo.dist);
1146
1170
  const watchers = watchRepo(repo);
1147
- await new Promise((resolve) => server.listen(port, "0.0.0.0", resolve));
1148
- const address = server.address();
1149
- const bound = typeof address === "object" && address !== null ? address.port : port;
1171
+ let bound;
1172
+ try {
1173
+ bound = await listen(server, port);
1174
+ } catch (error) {
1175
+ for (const watcher of watchers) watcher.close();
1176
+ throw error;
1177
+ }
1150
1178
  const url = `http://${lanAddress()}:${bound}/`;
1151
1179
  info(`serving ${repo.dist} on ${url}`);
1152
1180
  for (const list of lists) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aletheia-ios/tools",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "The aletheia CLI: build, check, pack, index and serve source packages",
5
5
  "license": "MIT",
6
6
  "repository": {