naro-mcp 0.9.1 → 0.10.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.
Files changed (2) hide show
  1. package/dist/index.js +105 -20
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1179,6 +1179,35 @@ function backendInfo(body) {
1179
1179
  turningOff: body.turningOff === true
1180
1180
  };
1181
1181
  }
1182
+ function authConfig(body) {
1183
+ return {
1184
+ ...body,
1185
+ signupsEnabled: typeof body.signupsEnabled === "boolean" ? body.signupsEnabled : true,
1186
+ passwordMinLength: typeof body.passwordMinLength === "number" ? body.passwordMinLength : 6
1187
+ };
1188
+ }
1189
+ function isRecord(value) {
1190
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1191
+ }
1192
+ async function authChange(answer) {
1193
+ let body;
1194
+ try {
1195
+ body = await answer;
1196
+ } catch (error51) {
1197
+ const details = isNaroError(error51) ? error51.details : void 0;
1198
+ if (isNaroError(error51) && error51.code === "BACKEND_PROVISION_FAILED" && isRecord(details?.auth) && isRecord(details.backend))
1199
+ throw new NaroError(error51.code, error51.message, {
1200
+ ...error51.status !== void 0 ? { status: error51.status } : {},
1201
+ details: {
1202
+ ...details,
1203
+ auth: authConfig(details.auth),
1204
+ backend: backendInfo(details.backend)
1205
+ }
1206
+ });
1207
+ throw error51;
1208
+ }
1209
+ return { auth: authConfig(body.auth), backend: backendInfo(body.backend) };
1210
+ }
1182
1211
  var BackendApi = class {
1183
1212
  constructor(client) {
1184
1213
  this.client = client;
@@ -1311,11 +1340,13 @@ var BackendApi = class {
1311
1340
  * and the callback URLs to register with the providers. Never a secret.
1312
1341
  */
1313
1342
  async auth(projectId) {
1314
- return this.client.request(
1315
- this.path(projectId, "/auth"),
1316
- {
1317
- context: "Read sign-in settings"
1318
- }
1343
+ return authConfig(
1344
+ await this.client.request(
1345
+ this.path(projectId, "/auth"),
1346
+ {
1347
+ context: "Read sign-in settings"
1348
+ }
1349
+ )
1319
1350
  );
1320
1351
  }
1321
1352
  /**
@@ -1324,32 +1355,86 @@ var BackendApi = class {
1324
1355
  * (nothing is saved), `BACKEND_NOT_READY` before the first provision,
1325
1356
  * `BACKEND_OFF` while the backend is turned off (nothing is saved),
1326
1357
  * `VERIFICATION_NEEDS_EMAIL` for a state where nobody could sign in. A
1327
- * failed upload is not an error — `backend.status` says `error` and the
1328
- * settings are saved; `enable` finishes. Two minutes, like enable.
1358
+ * failed upload throws `BACKEND_PROVISION_FAILED` (502): the settings are
1359
+ * saved, the message says whether the worker runs them yet, `details`
1360
+ * holds `{ auth, backend }`, and `enable` finishes. (A control plane from
1361
+ * before that resolves with `backend.status` `error` instead.) Two
1362
+ * minutes, like enable.
1329
1363
  */
1330
1364
  async setAuth(projectId, patch) {
1331
- const answer = await this.client.request(
1332
- this.path(projectId, "/auth"),
1333
- {
1365
+ return authChange(
1366
+ this.client.request(this.path(projectId, "/auth"), {
1334
1367
  method: "PUT",
1335
1368
  body: patch,
1336
1369
  context: "Change sign-in settings",
1337
1370
  timeoutMs: PROVISION_TIMEOUT_MS
1338
- }
1371
+ })
1339
1372
  );
1340
- return { auth: answer.auth, backend: backendInfo(answer.backend) };
1341
1373
  }
1342
1374
  /** Removes email or one provider; the same answer as `setAuth`. */
1343
1375
  async removeAuth(projectId, target) {
1376
+ return authChange(
1377
+ this.client.request(
1378
+ this.path(projectId, `/auth?target=${encodeURIComponent(target)}`),
1379
+ {
1380
+ method: "DELETE",
1381
+ context: "Change sign-in settings",
1382
+ timeoutMs: PROVISION_TIMEOUT_MS
1383
+ }
1384
+ )
1385
+ );
1386
+ }
1387
+ /**
1388
+ * The project's users, newest first (spec 2026-09-26 §2.2): page 1 and 50
1389
+ * a page unless given, at most 1000. `database.read`. `BACKEND_OFF` while
1390
+ * the backend is turned off, `BACKEND_NOT_READY` before it is ready,
1391
+ * `BACKEND_OUTDATED` while its Naro worker predates user management
1392
+ * (`enable` updates it), `BACKEND_UNAVAILABLE` when it cannot be reached.
1393
+ */
1394
+ async listUsers(projectId, options2 = {}) {
1395
+ const query = new URLSearchParams();
1396
+ if (options2.page !== void 0) query.set("page", String(options2.page));
1397
+ if (options2.perPage !== void 0)
1398
+ query.set("perPage", String(options2.perPage));
1399
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
1400
+ const body = await this.client.request(
1401
+ this.path(projectId, `/users${suffix}`),
1402
+ { context: "List users" }
1403
+ );
1404
+ return { users: body.users, total: body.total };
1405
+ }
1406
+ /**
1407
+ * Creates a user with a password, confirmed unless `emailConfirm: false`
1408
+ * — also while sign-ups are closed and while sign-in waits for a
1409
+ * confirmed email. A username-only user answers `email: null`.
1410
+ * `database.write`. The Naro worker's refusals come through as it said
1411
+ * them: `USERNAME_TAKEN` (409), `USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL`
1412
+ * (422), `PASSWORD_TOO_SHORT` ("Use at least {n} characters."),
1413
+ * `VALIDATION_ERROR`, `WRITE_QUOTA_EXCEEDED` (429, `details.retryAfter`).
1414
+ */
1415
+ async createUser(projectId, input) {
1416
+ const body = { password: input.password };
1417
+ if (input.email !== void 0) body.email = input.email;
1418
+ if (input.username !== void 0) body.username = input.username;
1419
+ if (input.emailConfirm !== void 0)
1420
+ body.emailConfirm = input.emailConfirm;
1344
1421
  const answer = await this.client.request(
1345
- this.path(projectId, `/auth?target=${encodeURIComponent(target)}`),
1346
- {
1347
- method: "DELETE",
1348
- context: "Change sign-in settings",
1349
- timeoutMs: PROVISION_TIMEOUT_MS
1350
- }
1422
+ this.path(projectId, "/users"),
1423
+ { method: "POST", body, context: "Create user" }
1424
+ );
1425
+ return answer.user;
1426
+ }
1427
+ /**
1428
+ * Deletes a user with its sign-in methods, and ends its sessions. Answers
1429
+ * the user it was. `USER_NOT_FOUND` (404) for an id that is not one.
1430
+ * `database.write`.
1431
+ */
1432
+ async deleteUser(projectId, userId) {
1433
+ const answer = await this.client.request(
1434
+ this.path(projectId, `/users/${encodeURIComponent(userId)}`),
1435
+ { method: "DELETE", context: "Delete user" }
1351
1436
  );
1352
- return { auth: answer.auth, backend: backendInfo(answer.backend) };
1437
+ return answer.user;
1353
1438
  }
1354
1439
  /** Every stored policy, by table name. Tables without one deny anon and signed-in requests. */
1355
1440
  async policies(projectId) {
@@ -18339,7 +18424,7 @@ function toolErrorJson(error51) {
18339
18424
  }
18340
18425
 
18341
18426
  // src/server.ts
18342
- var SERVER_VERSION = "0.9.1";
18427
+ var SERVER_VERSION = "0.10.0";
18343
18428
  function visibleTools(options2) {
18344
18429
  const { features, readOnly } = options2;
18345
18430
  return TOOLS.flatMap((tool) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naro-mcp",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "naro-mcp": "./dist/index.js"
@@ -18,15 +18,15 @@
18
18
  "dependencies": {
19
19
  "@modelcontextprotocol/sdk": "^1.0.0",
20
20
  "@supabase/supabase-js": "2.112.3",
21
- "naro-cli": "0.9.1"
21
+ "naro-cli": "0.10.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "tsup": "8.5.0",
25
25
  "tsx": "4.23.12",
26
26
  "typescript": "7.0.2",
27
27
  "vitest": "3.2.7",
28
- "@next-deploy/sdk": "0.1.0",
29
- "@next-deploy/config": "0.1.0"
28
+ "@next-deploy/config": "0.1.0",
29
+ "@next-deploy/sdk": "0.1.0"
30
30
  },
31
31
  "scripts": {
32
32
  "build": "tsup",