@pome-sh/cli 0.21.13 → 0.21.15

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.
@@ -1,7 +1,8 @@
1
- export { LINEAR_CHECKS } from './chunk-3QVSXFJI.js';
1
+ export { LINEAR_CHECKS } from './chunk-XBT6ZLBG.js';
2
2
  import { MCP_PAGE_MAX, defaultSeedState, linearSeedSchema, notFound, badUserInput, MCP_PAGE_DEFAULT, DEFAULT_LINEAR_EMAIL, RELAY_PAGE_MAX, RELAY_PAGE_DEFAULT, STATE_EXPORT_CAP, parseSeed, DEFAULT_LINEAR_CLOCK, LINEAR_PROVIDER_TOKEN_PREFIX, DEFAULT_LINEAR_SID, DEFAULT_SCOPES, linearErrorEnvelope, unauthorizedEnvelope, unsupportedEnvelope, assertWebhookUrl, ACCESS_TOKEN_TTL_SECONDS, OAUTH_CODE_TTL_SECONDS, TITLE_MAX_BYTES, BODY_MAX_BYTES, LinearTwinError, GRAPHQL_QUERY_MAX_BYTES, GRAPHQL_SELECTION_DEPTH_MAX } from './chunk-ZKID2HS3.js';
3
3
  export { DEFAULT_LINEAR_CLOCK, DEFAULT_LINEAR_EMAIL, DEFAULT_LINEAR_PORT, DEFAULT_LINEAR_SID, DEFAULT_LINEAR_TOKEN, LINEAR_PROVIDER_TOKEN_PREFIX, LinearTwinError, STATE_EXPORT_CAP, assertWebhookUrl, defaultSeedState, linearErrorEnvelope, linearSeedSchema, loadSeedFromEnv, parseSeed, unauthorizedEnvelope, unsupportedEnvelope, webhookUrlError } from './chunk-ZKID2HS3.js';
4
- import './chunk-NY55QTVQ.js';
4
+ import './chunk-JWJYNAWI.js';
5
+ import { declareRouteInputs, mountDeclaredRoute, UndeclaredInputError } from './chunk-4MQULI7E.js';
5
6
  import { loadMcpToolFixture, deriveMcpToolTable, openTwinDatabase, defineTwin, createApp } from './chunk-TV5S6WQV.js';
6
7
  import './chunk-VBATFCWR.js';
7
8
  import './chunk-SG6ZTIMT.js';
@@ -3358,16 +3359,105 @@ function shouldRedact(key) {
3358
3359
  return true;
3359
3360
  return false;
3360
3361
  }
3362
+ var VARIABLES_STRING = z.string().optional();
3363
+ var VARIABLES_OBJECT = z.union([z.record(z.string(), z.unknown()), z.string()]).optional();
3364
+ var AUTHORIZE_PARAMS = {
3365
+ client_id: z.string().optional(),
3366
+ redirect_uri: z.string().optional(),
3367
+ state: z.string().optional(),
3368
+ scope: z.string().optional(),
3369
+ actor: z.string().optional(),
3370
+ code_challenge: z.string().optional(),
3371
+ code_challenge_method: z.string().optional()
3372
+ };
3373
+ var LINEAR_ROUTES = {
3374
+ graphqlGet: declareRouteInputs({
3375
+ method: "GET",
3376
+ path: "/graphql",
3377
+ query: {
3378
+ query: z.string().optional(),
3379
+ variables: VARIABLES_STRING,
3380
+ operationName: z.string().optional()
3381
+ }
3382
+ }),
3383
+ graphqlPost: declareRouteInputs({
3384
+ method: "POST",
3385
+ path: "/graphql",
3386
+ bodyEncoding: "form",
3387
+ body: {
3388
+ query: z.string().optional(),
3389
+ variables: VARIABLES_OBJECT,
3390
+ operationName: z.string().optional()
3391
+ }
3392
+ }),
3393
+ oauthAuthorize: declareRouteInputs({
3394
+ method: "GET",
3395
+ path: "/oauth/authorize",
3396
+ query: { ...AUTHORIZE_PARAMS, response_type: z.string().optional() }
3397
+ }),
3398
+ oauthAuthorizeCallback: declareRouteInputs({
3399
+ method: "POST",
3400
+ path: "/oauth/authorize/callback",
3401
+ bodyEncoding: "form",
3402
+ // `user_ref` is the twin's own field: the consent page renders one form per
3403
+ // Linear user and posts back which one was picked. Real Linear has no
3404
+ // equivalent, and declaring it says so out loud.
3405
+ body: { ...AUTHORIZE_PARAMS, user_ref: z.string().optional() }
3406
+ }),
3407
+ oauthToken: declareRouteInputs({
3408
+ method: "POST",
3409
+ path: "/oauth/token",
3410
+ bodyEncoding: "form",
3411
+ // Client credentials arrive EITHER as HTTP Basic or as body fields, so both
3412
+ // are declared; `clientCredentials()` prefers the header.
3413
+ headers: { Authorization: z.string().optional() },
3414
+ body: {
3415
+ grant_type: z.string().optional(),
3416
+ client_id: z.string().optional(),
3417
+ client_secret: z.string().optional(),
3418
+ code: z.string().optional(),
3419
+ redirect_uri: z.string().optional(),
3420
+ code_verifier: z.string().optional(),
3421
+ refresh_token: z.string().optional(),
3422
+ scope: z.string().optional()
3423
+ }
3424
+ }),
3425
+ oauthRevoke: declareRouteInputs({
3426
+ method: "POST",
3427
+ path: "/oauth/revoke",
3428
+ bodyEncoding: "form",
3429
+ body: {
3430
+ token: z.string().optional(),
3431
+ access_token: z.string().optional(),
3432
+ refresh_token: z.string().optional()
3433
+ }
3434
+ })
3435
+ };
3436
+
3437
+ // ../packages/twin-linear/dist/src/oauth/routes.js
3438
+ async function parseDeclared(declaration, c, onUndeclared) {
3439
+ try {
3440
+ return { input: await declaration.parse(c.req) };
3441
+ } catch (error) {
3442
+ if (error instanceof UndeclaredInputError)
3443
+ return { response: onUndeclared(error) };
3444
+ throw error;
3445
+ }
3446
+ }
3361
3447
  function registerOAuthRoutes(app, commands) {
3362
- app.get("/oauth/authorize", (c) => {
3363
- const clientId = c.req.query("client_id") ?? "";
3364
- const redirectUri = c.req.query("redirect_uri") ?? "";
3365
- const responseType = c.req.query("response_type") ?? "code";
3366
- const state = c.req.query("state") ?? "";
3367
- const scope = c.req.query("scope") ?? "read";
3368
- const requestedActor = normalizeActor(c.req.query("actor"));
3369
- const codeChallenge = c.req.query("code_challenge") ?? "";
3370
- const codeChallengeMethod = c.req.query("code_challenge_method") ?? "";
3448
+ mountDeclaredRoute(app, LINEAR_ROUTES.oauthAuthorize, async (c) => {
3449
+ const parsed = await parseDeclared(LINEAR_ROUTES.oauthAuthorize, c, (error) => c.html(errorPage("Unknown parameter", `The ${error.first} parameter is not supported.`), 400));
3450
+ if ("response" in parsed)
3451
+ return parsed.response;
3452
+ const query = parsed.input.query;
3453
+ const clientId = query.client_id ?? "";
3454
+ const redirectUri = query.redirect_uri ?? "";
3455
+ const responseType = query.response_type ?? "code";
3456
+ const state = query.state ?? "";
3457
+ const scope = query.scope ?? "read";
3458
+ const requestedActor = normalizeActor(query.actor);
3459
+ const codeChallenge = query.code_challenge ?? "";
3460
+ const codeChallengeMethod = query.code_challenge_method ?? "";
3371
3461
  if (responseType !== "code") {
3372
3462
  return c.html(errorPage("Unsupported response_type", "Only response_type=code is supported."), 400);
3373
3463
  }
@@ -3427,8 +3517,11 @@ function registerOAuthRoutes(app, commands) {
3427
3517
  })).join("\n");
3428
3518
  return c.html(cardPage(title, `Continue to <strong>${escapeHtml(appName)}</strong> with scopes <strong>${escapeHtml(requestedScopes.join(", "))}</strong>.`, buttons || '<p class="empty">No users in the Linear twin store.</p>'));
3429
3519
  });
3430
- app.post("/oauth/authorize/callback", async (c) => {
3431
- const body = await c.req.parseBody();
3520
+ mountDeclaredRoute(app, LINEAR_ROUTES.oauthAuthorizeCallback, async (c) => {
3521
+ const parsed = await parseDeclared(LINEAR_ROUTES.oauthAuthorizeCallback, c, (error) => c.html(errorPage("Unknown parameter", `The ${error.first} parameter is not supported.`), 400));
3522
+ if ("response" in parsed)
3523
+ return parsed.response;
3524
+ const body = parsed.input.body;
3432
3525
  const clientId = bodyStr(body.client_id);
3433
3526
  const redirectUri = bodyStr(body.redirect_uri);
3434
3527
  const state = bodyStr(body.state);
@@ -3479,10 +3572,13 @@ function registerOAuthRoutes(app, commands) {
3479
3572
  url.searchParams.set("state", state);
3480
3573
  return c.redirect(url.toString());
3481
3574
  });
3482
- app.post("/oauth/token", async (c) => {
3483
- const body = await c.req.parseBody();
3575
+ mountDeclaredRoute(app, LINEAR_ROUTES.oauthToken, async (c) => {
3576
+ const parsed = await parseDeclared(LINEAR_ROUTES.oauthToken, c, (error) => oauthError("invalid_request", `Unknown parameter: ${error.first}.`));
3577
+ if ("response" in parsed)
3578
+ return parsed.response;
3579
+ const { body, header } = parsed.input;
3484
3580
  const grantType = bodyStr(body.grant_type);
3485
- const clientAuth = clientCredentials(c.req.header("Authorization"), body);
3581
+ const clientAuth = clientCredentials(header.Authorization, body);
3486
3582
  const oauthApp = requireRegisteredOAuthApp(commands, clientAuth.clientId);
3487
3583
  if (!oauthApp) {
3488
3584
  return oauthError("invalid_client", "The OAuth app is not registered.");
@@ -3552,8 +3648,11 @@ function registerOAuthRoutes(app, commands) {
3552
3648
  }
3553
3649
  return oauthError("unsupported_grant_type", "Only authorization_code, refresh_token, and client_credentials are supported.");
3554
3650
  });
3555
- app.post("/oauth/revoke", async (c) => {
3556
- const body = await c.req.parseBody();
3651
+ mountDeclaredRoute(app, LINEAR_ROUTES.oauthRevoke, async (c) => {
3652
+ const parsed = await parseDeclared(LINEAR_ROUTES.oauthRevoke, c, (error) => oauthError("invalid_request", `Unknown parameter: ${error.first}.`));
3653
+ if ("response" in parsed)
3654
+ return parsed.response;
3655
+ const body = parsed.input.body;
3557
3656
  const value = bodyStr(body.token) || bodyStr(body.access_token) || bodyStr(body.refresh_token);
3558
3657
  if (value)
3559
3658
  commands.revokeToken(value);
@@ -4953,21 +5052,34 @@ var linearGraphQLSchema = buildSchema(`
4953
5052
 
4954
5053
  // ../packages/twin-linear/dist/src/graphql/routes.js
4955
5054
  function registerGraphqlRoutes(app, ctx) {
4956
- app.get("/graphql", ctx.recorder.handle({ mutation: false }, async (c) => {
4957
- const query = c.req.query("query") ?? "";
4958
- return executeRecordedGraphQL(ctx, c, query, {
4959
- variables: parseVariables(c.req.query("variables")),
4960
- operationName: c.req.query("operationName") ?? void 0
5055
+ mountDeclaredRoute(app, LINEAR_ROUTES.graphqlGet, ctx.recorder.handle({ mutation: false }, async (c) => {
5056
+ const { query } = await parseDeclared2(LINEAR_ROUTES.graphqlGet, c);
5057
+ return executeRecordedGraphQL(ctx, c, query.query ?? "", {
5058
+ variables: parseVariables(query.variables),
5059
+ operationName: query.operationName
4961
5060
  });
4962
5061
  }));
4963
- app.post("/graphql", ctx.recorder.handle({ mutation: false }, async (c) => {
4964
- const body = await readGraphQLBody(c);
4965
- return executeRecordedGraphQL(ctx, c, body.query, {
4966
- variables: body.variables,
5062
+ mountDeclaredRoute(app, LINEAR_ROUTES.graphqlPost, ctx.recorder.handle({ mutation: false }, async (c) => {
5063
+ const { body } = await parseDeclared2(LINEAR_ROUTES.graphqlPost, c);
5064
+ return executeRecordedGraphQL(ctx, c, body.query ?? "", {
5065
+ // Form-posted variables arrive as a JSON string, JSON-posted ones as an
5066
+ // object. The declaration accepts both spellings, so both are handled
5067
+ // here rather than at two content-type-sniffing call sites.
5068
+ variables: typeof body.variables === "string" ? parseVariables(body.variables) : body.variables,
4967
5069
  operationName: body.operationName
4968
5070
  });
4969
5071
  }));
4970
5072
  }
5073
+ async function parseDeclared2(declaration, c) {
5074
+ try {
5075
+ return await declaration.parse(c.req);
5076
+ } catch (error) {
5077
+ if (error instanceof UndeclaredInputError) {
5078
+ badUserInput(`Unknown ${error.location} parameter: ${error.first}`);
5079
+ }
5080
+ throw error;
5081
+ }
5082
+ }
4971
5083
  async function executeRecordedGraphQL(ctx, c, query, opts) {
4972
5084
  const before = ctx.domain.exportState();
4973
5085
  const result = await runGraphQL(ctx.domain, c, query, opts);
@@ -5058,23 +5170,6 @@ function isMutationOperation(source, operationName) {
5058
5170
  return /^\s*mutation\b/i.test(source);
5059
5171
  }
5060
5172
  }
5061
- async function readGraphQLBody(c) {
5062
- const contentType = c.req.header("content-type") ?? "";
5063
- if (contentType.includes("application/x-www-form-urlencoded")) {
5064
- const body2 = await c.req.parseBody();
5065
- return {
5066
- query: typeof body2.query === "string" ? body2.query : "",
5067
- variables: parseVariables(typeof body2.variables === "string" ? body2.variables : void 0),
5068
- operationName: typeof body2.operationName === "string" && body2.operationName ? body2.operationName : void 0
5069
- };
5070
- }
5071
- const body = await c.req.json().catch(() => ({}));
5072
- return {
5073
- query: typeof body.query === "string" ? body.query : "",
5074
- variables: isRecord(body.variables) ? body.variables : void 0,
5075
- operationName: typeof body.operationName === "string" ? body.operationName : void 0
5076
- };
5077
- }
5078
5173
  function parseVariables(raw) {
5079
5174
  if (!raw)
5080
5175
  return void 0;