specli 0.0.18 → 0.0.20

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 (75) hide show
  1. package/README.md +3 -1
  2. package/dist/ai/tools.d.ts +6 -5
  3. package/dist/ai/tools.js +7 -20
  4. package/dist/ai/tools.test.js +7 -14
  5. package/dist/cli/compile.js +137 -61
  6. package/dist/cli.d.ts +0 -1
  7. package/dist/cli.js +0 -1
  8. package/package.json +1 -2
  9. package/src/ai/tools.test.ts +0 -83
  10. package/src/ai/tools.ts +0 -211
  11. package/src/cli/auth-requirements.test.ts +0 -27
  12. package/src/cli/auth-requirements.ts +0 -91
  13. package/src/cli/auth-schemes.test.ts +0 -66
  14. package/src/cli/auth-schemes.ts +0 -187
  15. package/src/cli/capabilities.test.ts +0 -94
  16. package/src/cli/capabilities.ts +0 -88
  17. package/src/cli/command-id.test.ts +0 -32
  18. package/src/cli/command-id.ts +0 -16
  19. package/src/cli/command-index.ts +0 -19
  20. package/src/cli/command-model.test.ts +0 -44
  21. package/src/cli/command-model.ts +0 -128
  22. package/src/cli/compile.ts +0 -109
  23. package/src/cli/crypto.ts +0 -9
  24. package/src/cli/derive-name.ts +0 -101
  25. package/src/cli/exec.ts +0 -72
  26. package/src/cli/main.ts +0 -255
  27. package/src/cli/naming.test.ts +0 -86
  28. package/src/cli/naming.ts +0 -224
  29. package/src/cli/operations.test.ts +0 -57
  30. package/src/cli/operations.ts +0 -152
  31. package/src/cli/params.test.ts +0 -70
  32. package/src/cli/params.ts +0 -71
  33. package/src/cli/pluralize.ts +0 -41
  34. package/src/cli/positional.test.ts +0 -65
  35. package/src/cli/positional.ts +0 -75
  36. package/src/cli/request-body.test.ts +0 -35
  37. package/src/cli/request-body.ts +0 -94
  38. package/src/cli/runtime/argv.ts +0 -14
  39. package/src/cli/runtime/auth/resolve.ts +0 -59
  40. package/src/cli/runtime/body-flags.test.ts +0 -261
  41. package/src/cli/runtime/body-flags.ts +0 -176
  42. package/src/cli/runtime/body.ts +0 -24
  43. package/src/cli/runtime/collect.ts +0 -6
  44. package/src/cli/runtime/compat.ts +0 -89
  45. package/src/cli/runtime/context.ts +0 -62
  46. package/src/cli/runtime/execute.ts +0 -147
  47. package/src/cli/runtime/generated.ts +0 -242
  48. package/src/cli/runtime/headers.ts +0 -37
  49. package/src/cli/runtime/index.ts +0 -3
  50. package/src/cli/runtime/profile/secrets.ts +0 -83
  51. package/src/cli/runtime/profile/store.ts +0 -100
  52. package/src/cli/runtime/request.test.ts +0 -375
  53. package/src/cli/runtime/request.ts +0 -390
  54. package/src/cli/runtime/server-url.ts +0 -45
  55. package/src/cli/runtime/template.ts +0 -26
  56. package/src/cli/runtime/validate/ajv.ts +0 -13
  57. package/src/cli/runtime/validate/coerce.test.ts +0 -98
  58. package/src/cli/runtime/validate/coerce.ts +0 -71
  59. package/src/cli/runtime/validate/error.ts +0 -29
  60. package/src/cli/runtime/validate/index.ts +0 -4
  61. package/src/cli/runtime/validate/schema.ts +0 -54
  62. package/src/cli/schema-shape.ts +0 -36
  63. package/src/cli/schema.ts +0 -76
  64. package/src/cli/server.test.ts +0 -55
  65. package/src/cli/server.ts +0 -167
  66. package/src/cli/spec-id.ts +0 -12
  67. package/src/cli/spec-loader.ts +0 -58
  68. package/src/cli/stable-json.ts +0 -35
  69. package/src/cli/strings.ts +0 -21
  70. package/src/cli/types.ts +0 -59
  71. package/src/cli.ts +0 -94
  72. package/src/compiled.ts +0 -24
  73. package/src/macros/env.ts +0 -21
  74. package/src/macros/spec.ts +0 -17
  75. package/src/macros/version.ts +0 -14
@@ -1,152 +0,0 @@
1
- import type {
2
- NormalizedOperation,
3
- NormalizedParameter,
4
- NormalizedRequestBody,
5
- OpenApiDoc,
6
- } from "./types.js";
7
-
8
- function operationKey(method: string, path: string): string {
9
- return `${method.toUpperCase()} ${path}`;
10
- }
11
-
12
- const HTTP_METHODS = [
13
- "get",
14
- "post",
15
- "put",
16
- "patch",
17
- "delete",
18
- "options",
19
- "head",
20
- "trace",
21
- ] as const;
22
-
23
- type RawParameter = {
24
- in?: string;
25
- name?: string;
26
- required?: boolean;
27
- description?: string;
28
- schema?: unknown;
29
- };
30
-
31
- type RawRequestBody = {
32
- required?: boolean;
33
- content?: Record<string, { schema?: unknown } | undefined>;
34
- };
35
-
36
- type RawOperation = {
37
- operationId?: string;
38
- tags?: string[];
39
- summary?: string;
40
- description?: string;
41
- deprecated?: boolean;
42
- security?: OpenApiDoc["security"];
43
- parameters?: RawParameter[];
44
- requestBody?: RawRequestBody;
45
- };
46
-
47
- type RawPathItem = {
48
- parameters?: RawParameter[];
49
- } & Partial<Record<(typeof HTTP_METHODS)[number], RawOperation>>;
50
-
51
- function normalizeParam(p: RawParameter): NormalizedParameter | undefined {
52
- if (!p || typeof p !== "object") return undefined;
53
- const loc = p.in;
54
- const name = p.name;
55
- if (
56
- loc !== "path" &&
57
- loc !== "query" &&
58
- loc !== "header" &&
59
- loc !== "cookie"
60
- ) {
61
- return undefined;
62
- }
63
- if (!name) return undefined;
64
-
65
- return {
66
- in: loc,
67
- name,
68
- required: Boolean(p.required || loc === "path"),
69
- description: p.description,
70
- schema: p.schema,
71
- };
72
- }
73
-
74
- function mergeParameters(
75
- pathParams: RawParameter[] | undefined,
76
- opParams: RawParameter[] | undefined,
77
- ): NormalizedParameter[] {
78
- const merged = new Map<string, NormalizedParameter>();
79
-
80
- for (const p of pathParams ?? []) {
81
- const normalized = normalizeParam(p);
82
- if (!normalized) continue;
83
- merged.set(`${normalized.in}:${normalized.name}`, normalized);
84
- }
85
-
86
- for (const p of opParams ?? []) {
87
- const normalized = normalizeParam(p);
88
- if (!normalized) continue;
89
- merged.set(`${normalized.in}:${normalized.name}`, normalized);
90
- }
91
-
92
- return [...merged.values()];
93
- }
94
-
95
- function normalizeRequestBody(
96
- rb: RawRequestBody | undefined,
97
- ): NormalizedRequestBody | undefined {
98
- if (!rb) return undefined;
99
-
100
- const content = rb.content ?? {};
101
- const contentTypes = Object.keys(content);
102
- const schemasByContentType: Record<string, unknown | undefined> = {};
103
-
104
- for (const contentType of contentTypes) {
105
- schemasByContentType[contentType] = content[contentType]?.schema;
106
- }
107
-
108
- return {
109
- required: Boolean(rb.required),
110
- contentTypes,
111
- schemasByContentType,
112
- };
113
- }
114
-
115
- export function indexOperations(doc: OpenApiDoc): NormalizedOperation[] {
116
- const out: NormalizedOperation[] = [];
117
- const paths = doc.paths ?? {};
118
-
119
- for (const [path, rawPathItem] of Object.entries(paths)) {
120
- if (!rawPathItem || typeof rawPathItem !== "object") continue;
121
-
122
- const pathItem = rawPathItem as RawPathItem;
123
-
124
- for (const method of HTTP_METHODS) {
125
- const op = pathItem[method];
126
- if (!op) continue;
127
-
128
- const parameters = mergeParameters(pathItem.parameters, op.parameters);
129
- const normalizedMethod = method.toUpperCase();
130
- out.push({
131
- key: operationKey(normalizedMethod, path),
132
- method: normalizedMethod,
133
- path,
134
- operationId: op.operationId,
135
- tags: op.tags ?? [],
136
- summary: op.summary,
137
- description: op.description,
138
- deprecated: op.deprecated,
139
- security: (op.security ?? doc.security) as OpenApiDoc["security"],
140
- parameters,
141
- requestBody: normalizeRequestBody(op.requestBody),
142
- });
143
- }
144
- }
145
-
146
- out.sort((a, b) => {
147
- if (a.path !== b.path) return a.path.localeCompare(b.path);
148
- return a.method.localeCompare(b.method);
149
- });
150
-
151
- return out;
152
- }
@@ -1,70 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import { deriveParamSpecs } from "./params.js";
4
- import type { NormalizedOperation } from "./types.js";
5
-
6
- describe("deriveParamSpecs", () => {
7
- test("derives basic types + flags", () => {
8
- const op: NormalizedOperation = {
9
- key: "GET /contacts",
10
- method: "GET",
11
- path: "/contacts",
12
- tags: [],
13
- parameters: [
14
- {
15
- in: "query",
16
- name: "limit",
17
- required: false,
18
- schema: {
19
- type: "integer",
20
- format: "int32",
21
- enum: ["1", "2"],
22
- },
23
- },
24
- {
25
- in: "header",
26
- name: "X-Request-Id",
27
- required: false,
28
- schema: { type: "string" },
29
- },
30
- ],
31
- };
32
-
33
- const specs = deriveParamSpecs(op);
34
- expect(specs).toHaveLength(2);
35
-
36
- const limit = specs.find((p) => p.name === "limit");
37
- expect(limit?.kind).toBe("flag");
38
- expect(limit?.flag).toBe("--limit");
39
- expect(limit?.type).toBe("integer");
40
- expect(limit?.format).toBe("int32");
41
- expect(limit?.enum).toEqual(["1", "2"]);
42
-
43
- const reqId = specs.find((p) => p.name === "X-Request-Id");
44
- expect(reqId?.kind).toBe("flag");
45
- expect(reqId?.flag).toBe("--x-request-id");
46
- expect(reqId?.type).toBe("string");
47
- });
48
-
49
- test("derives array item types", () => {
50
- const op: NormalizedOperation = {
51
- key: "GET /things",
52
- method: "GET",
53
- path: "/things",
54
- tags: [],
55
- parameters: [
56
- {
57
- in: "query",
58
- name: "ids",
59
- required: false,
60
- schema: { type: "array", items: { type: "integer" } },
61
- },
62
- ],
63
- };
64
-
65
- const specs = deriveParamSpecs(op);
66
- expect(specs).toHaveLength(1);
67
- expect(specs[0]?.type).toBe("array");
68
- expect(specs[0]?.itemType).toBe("integer");
69
- });
70
- });
package/src/cli/params.ts DELETED
@@ -1,71 +0,0 @@
1
- import {
2
- getSchemaEnumStrings,
3
- getSchemaFormat,
4
- getSchemaType,
5
- } from "./schema-shape.js";
6
- import { kebabCase } from "./strings.js";
7
- import type { NormalizedOperation, NormalizedParameter } from "./types.js";
8
-
9
- export type ParamType = import("./schema-shape.js").ParamType;
10
-
11
- export type ParamSpec = {
12
- kind: "positional" | "flag";
13
- in: NormalizedParameter["in"];
14
- name: string;
15
- flag: string;
16
- required: boolean;
17
- description?: string;
18
- type: ParamType;
19
- format?: string;
20
- enum?: string[];
21
-
22
- // Arrays
23
- itemType?: ParamType;
24
- itemFormat?: string;
25
- itemEnum?: string[];
26
-
27
- // Original schema for Ajv validation and future advanced flag expansion.
28
- schema?: import("./types.js").JsonSchema;
29
- };
30
-
31
- export function deriveParamSpecs(op: NormalizedOperation): ParamSpec[] {
32
- const out: ParamSpec[] = [];
33
-
34
- for (const p of op.parameters) {
35
- const flag = `--${kebabCase(p.name)}`;
36
- const type = getSchemaType(p.schema);
37
- const schemaObj =
38
- p.schema && typeof p.schema === "object"
39
- ? (p.schema as import("./types.js").JsonSchema)
40
- : undefined;
41
-
42
- const itemsSchema =
43
- schemaObj && type === "array" && typeof schemaObj.items === "object"
44
- ? (schemaObj.items as unknown)
45
- : undefined;
46
-
47
- out.push({
48
- kind: p.in === "path" ? "positional" : "flag",
49
- in: p.in,
50
- name: p.name,
51
- flag,
52
- required: p.required,
53
- description: p.description,
54
- type,
55
- format: getSchemaFormat(p.schema),
56
- enum: getSchemaEnumStrings(p.schema),
57
- itemType: type === "array" ? getSchemaType(itemsSchema) : undefined,
58
- itemFormat: type === "array" ? getSchemaFormat(itemsSchema) : undefined,
59
- itemEnum:
60
- type === "array" ? getSchemaEnumStrings(itemsSchema) : undefined,
61
- schema: schemaObj,
62
- });
63
- }
64
-
65
- out.sort((a, b) => {
66
- if (a.in !== b.in) return a.in.localeCompare(b.in);
67
- return a.name.localeCompare(b.name);
68
- });
69
-
70
- return out;
71
- }
@@ -1,41 +0,0 @@
1
- const IRREGULAR: Record<string, string> = {
2
- person: "people",
3
- man: "men",
4
- woman: "women",
5
- child: "children",
6
- tooth: "teeth",
7
- foot: "feet",
8
- mouse: "mice",
9
- goose: "geese",
10
- };
11
-
12
- const UNCOUNTABLE = new Set([
13
- "metadata",
14
- "information",
15
- "equipment",
16
- "money",
17
- "series",
18
- "species",
19
- ]);
20
-
21
- export function pluralize(word: string): string {
22
- const w = word.trim();
23
- if (!w) return w;
24
-
25
- const lower = w.toLowerCase();
26
- if (UNCOUNTABLE.has(lower)) return lower;
27
- if (IRREGULAR[lower]) return IRREGULAR[lower];
28
-
29
- // already plural-ish
30
- if (lower.endsWith("s")) return lower;
31
-
32
- if (/[bcdfghjklmnpqrstvwxyz]y$/.test(lower)) {
33
- return lower.replace(/y$/, "ies");
34
- }
35
-
36
- if (/(ch|sh|x|z)$/.test(lower)) {
37
- return `${lower}es`;
38
- }
39
-
40
- return `${lower}s`;
41
- }
@@ -1,65 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import type { ActionShapeForCli } from "./positional.js";
3
- import { deriveFlags, derivePositionals } from "./positional.js";
4
-
5
- describe("derivePositionals", () => {
6
- test("returns ordered positionals from pathArgs", () => {
7
- const action: ActionShapeForCli = {
8
- pathArgs: ["id"],
9
- params: [
10
- {
11
- kind: "positional",
12
- in: "path",
13
- name: "id",
14
- flag: "--id",
15
- required: true,
16
- type: "string",
17
- },
18
- ],
19
- };
20
-
21
- const pos = derivePositionals(action);
22
- expect(pos).toEqual([
23
- {
24
- name: "id",
25
- required: true,
26
- type: "string",
27
- format: undefined,
28
- enum: undefined,
29
- description: undefined,
30
- },
31
- ]);
32
- });
33
- });
34
-
35
- describe("deriveFlags", () => {
36
- test("returns only flag params", () => {
37
- const action: ActionShapeForCli = {
38
- pathArgs: [],
39
- params: [
40
- {
41
- kind: "flag",
42
- in: "query",
43
- name: "limit",
44
- flag: "--limit",
45
- required: false,
46
- type: "integer",
47
- },
48
- ],
49
- };
50
-
51
- const flags = deriveFlags(action);
52
- expect(flags.flags).toEqual([
53
- {
54
- in: "query",
55
- name: "limit",
56
- flag: "--limit",
57
- required: false,
58
- description: undefined,
59
- type: "integer",
60
- format: undefined,
61
- enum: undefined,
62
- },
63
- ]);
64
- });
65
- });
@@ -1,75 +0,0 @@
1
- import type { ParamSpec } from "./params.js";
2
-
3
- export type ActionShapeForCli = {
4
- pathArgs: string[];
5
- params: ParamSpec[];
6
- };
7
-
8
- export type PositionalArg = {
9
- name: string;
10
- required: boolean;
11
- description?: string;
12
- type: import("./schema-shape.js").ParamType;
13
- format?: string;
14
- enum?: string[];
15
- };
16
-
17
- export type FlagsIndex = {
18
- flags: Array<
19
- Pick<
20
- import("./params.js").ParamSpec,
21
- | "in"
22
- | "name"
23
- | "flag"
24
- | "required"
25
- | "description"
26
- | "type"
27
- | "format"
28
- | "enum"
29
- | "itemType"
30
- | "itemFormat"
31
- | "itemEnum"
32
- >
33
- >;
34
- };
35
-
36
- export function derivePositionals(action: ActionShapeForCli): PositionalArg[] {
37
- const byName = new Map<string, PositionalArg>();
38
-
39
- // Use pathArgs order; match metadata from params when available.
40
- for (const name of action.pathArgs) {
41
- const p = action.params.find(
42
- (x: ParamSpec) => x.in === "path" && x.name === name,
43
- );
44
- byName.set(name, {
45
- name,
46
- required: true,
47
- description: p?.description,
48
- type: p?.type ?? "unknown",
49
- format: p?.format,
50
- enum: p?.enum,
51
- });
52
- }
53
-
54
- return [...byName.values()];
55
- }
56
-
57
- export function deriveFlags(action: ActionShapeForCli): FlagsIndex {
58
- return {
59
- flags: action.params
60
- .filter((p: ParamSpec) => p.kind === "flag")
61
- .map((p: ParamSpec) => ({
62
- in: p.in,
63
- name: p.name,
64
- flag: p.flag,
65
- required: p.required,
66
- description: p.description,
67
- type: p.type,
68
- format: p.format,
69
- enum: p.enum,
70
- itemType: p.itemType,
71
- itemFormat: p.itemFormat,
72
- itemEnum: p.itemEnum,
73
- })),
74
- };
75
- }
@@ -1,35 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import { deriveRequestBodyInfo } from "./request-body.js";
4
- import type { NormalizedOperation } from "./types.js";
5
-
6
- describe("deriveRequestBodyInfo", () => {
7
- test("summarizes content types and convenience flags", () => {
8
- const op: NormalizedOperation = {
9
- key: "POST /contacts",
10
- method: "POST",
11
- path: "/contacts",
12
- tags: [],
13
- parameters: [],
14
- requestBody: {
15
- required: true,
16
- contentTypes: ["application/x-www-form-urlencoded", "application/json"],
17
- schemasByContentType: {
18
- "application/json": { type: "object" },
19
- "application/x-www-form-urlencoded": { type: "object" },
20
- },
21
- },
22
- };
23
-
24
- const info = deriveRequestBodyInfo(op);
25
- expect(info?.required).toBe(true);
26
- expect(info?.hasJson).toBe(true);
27
- expect(info?.hasFormUrlEncoded).toBe(true);
28
- expect(info?.hasMultipart).toBe(false);
29
- expect(info?.content.map((c) => c.contentType)).toEqual([
30
- "application/json",
31
- "application/x-www-form-urlencoded",
32
- ]);
33
- expect(info?.preferredSchema).toEqual({ type: "object" });
34
- });
35
- });
@@ -1,94 +0,0 @@
1
- import {
2
- getSchemaEnumStrings,
3
- getSchemaFormat,
4
- getSchemaType,
5
- } from "./schema-shape.js";
6
- import type {
7
- JsonSchema,
8
- NormalizedOperation,
9
- NormalizedRequestBody,
10
- } from "./types.js";
11
- import { isJsonSchema } from "./types.js";
12
-
13
- export type RequestBodyContent = {
14
- contentType: string;
15
- required: boolean;
16
- schemaType: import("./schema-shape.js").ParamType;
17
- schemaFormat?: string;
18
- schemaEnum?: string[];
19
- };
20
-
21
- export type RequestBodyInfo = {
22
- required: boolean;
23
- content: RequestBodyContent[];
24
- // Convenience flags for later arg generation.
25
- hasJson: boolean;
26
- hasFormUrlEncoded: boolean;
27
- hasMultipart: boolean;
28
-
29
- // Phase 1 planning: supported generic body inputs.
30
- bodyFlags: string[];
31
- preferredContentType?: string;
32
-
33
- // Original JSON Schema (for expanded flags + validation)
34
- preferredSchema?: JsonSchema;
35
- };
36
-
37
- function getRequestBody(
38
- op: NormalizedOperation,
39
- ): NormalizedRequestBody | undefined {
40
- return op.requestBody;
41
- }
42
-
43
- export function deriveRequestBodyInfo(
44
- op: NormalizedOperation,
45
- ): RequestBodyInfo | undefined {
46
- const rb = getRequestBody(op);
47
- if (!rb) return undefined;
48
-
49
- const content: RequestBodyContent[] = [];
50
- for (const contentType of rb.contentTypes) {
51
- const schema = rb.schemasByContentType[contentType];
52
- content.push({
53
- contentType,
54
- required: rb.required,
55
- schemaType: getSchemaType(schema),
56
- schemaFormat: getSchemaFormat(schema),
57
- schemaEnum: getSchemaEnumStrings(schema),
58
- });
59
- }
60
-
61
- content.sort((a, b) => a.contentType.localeCompare(b.contentType));
62
-
63
- const hasJson = content.some((c) => c.contentType.includes("json"));
64
- const hasFormUrlEncoded = content.some(
65
- (c) => c.contentType === "application/x-www-form-urlencoded",
66
- );
67
- const hasMultipart = content.some((c) =>
68
- c.contentType.startsWith("multipart/"),
69
- );
70
-
71
- const bodyFlags = ["--data", "--file"]; // always available when requestBody exists
72
-
73
- const preferredContentType =
74
- content.find((c) => c.contentType === "application/json")?.contentType ??
75
- content.find((c) => c.contentType.includes("json"))?.contentType ??
76
- content[0]?.contentType;
77
-
78
- const preferredSchema = preferredContentType
79
- ? rb.schemasByContentType[preferredContentType]
80
- : undefined;
81
-
82
- return {
83
- required: rb.required,
84
- content,
85
- hasJson,
86
- hasFormUrlEncoded,
87
- hasMultipart,
88
- bodyFlags,
89
- preferredContentType,
90
- preferredSchema: isJsonSchema(preferredSchema)
91
- ? preferredSchema
92
- : undefined,
93
- };
94
- }
@@ -1,14 +0,0 @@
1
- export function getArgValue(argv: string[], key: string): string | undefined {
2
- for (let i = 0; i < argv.length; i++) {
3
- const a = argv[i];
4
- if (!a) continue;
5
-
6
- if (a === key) return argv[i + 1];
7
- if (a.startsWith(`${key}=`)) return a.slice(key.length + 1);
8
- }
9
- return undefined;
10
- }
11
-
12
- export function hasAnyArg(argv: string[], names: string[]): boolean {
13
- return argv.some((a) => a && names.includes(a));
14
- }
@@ -1,59 +0,0 @@
1
- import type { AuthScheme } from "../../auth-schemes.js";
2
-
3
- export type AuthInputs = {
4
- flagAuthScheme?: string;
5
- profileAuthScheme?: string;
6
- embeddedAuthScheme?: string;
7
- hasStoredToken?: boolean;
8
- };
9
-
10
- const BEARER_COMPATIBLE_KINDS = new Set([
11
- "http-bearer",
12
- "oauth2",
13
- "openIdConnect",
14
- ]);
15
-
16
- export function resolveAuthScheme(
17
- authSchemes: AuthScheme[],
18
- required: import("../../auth-requirements.js").AuthSummary,
19
- inputs: AuthInputs,
20
- ): string | undefined {
21
- // Priority: CLI flag > profile > embedded default
22
- if (inputs.flagAuthScheme) return inputs.flagAuthScheme;
23
-
24
- if (
25
- inputs.profileAuthScheme &&
26
- authSchemes.some((s) => s.key === inputs.profileAuthScheme)
27
- ) {
28
- return inputs.profileAuthScheme;
29
- }
30
-
31
- if (
32
- inputs.embeddedAuthScheme &&
33
- authSchemes.some((s) => s.key === inputs.embeddedAuthScheme)
34
- ) {
35
- return inputs.embeddedAuthScheme;
36
- }
37
-
38
- // If operation requires exactly one scheme, choose it.
39
- const alts = required.alternatives;
40
- if (alts.length === 1 && alts[0]?.length === 1) return alts[0][0]?.key;
41
-
42
- // Otherwise if there is only one scheme in spec, pick it.
43
- if (authSchemes.length === 1) return authSchemes[0]?.key;
44
-
45
- // If user has a stored token and operation accepts a bearer-compatible scheme,
46
- // automatically pick the first one that matches.
47
- if (inputs.hasStoredToken && alts.length > 0) {
48
- for (const alt of alts) {
49
- if (alt.length !== 1) continue;
50
- const key = alt[0]?.key;
51
- const scheme = authSchemes.find((s) => s.key === key);
52
- if (scheme && BEARER_COMPATIBLE_KINDS.has(scheme.kind)) {
53
- return key;
54
- }
55
- }
56
- }
57
-
58
- return undefined;
59
- }