specli 0.0.1 → 0.0.3
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/README.md +76 -86
- package/cli.ts +4 -10
- package/package.json +8 -2
- package/src/cli/compile.ts +5 -28
- package/src/cli/derive-name.ts +2 -2
- package/src/cli/exec.ts +1 -1
- package/src/cli/main.ts +12 -27
- package/src/cli/runtime/auth/resolve.ts +10 -2
- package/src/cli/runtime/body-flags.ts +176 -0
- package/src/cli/runtime/execute.ts +41 -91
- package/src/cli/runtime/generated.ts +28 -93
- package/src/cli/runtime/profile/secrets.ts +1 -1
- package/src/cli/runtime/profile/store.ts +1 -1
- package/src/cli/runtime/request.ts +42 -152
- package/src/cli/stable-json.ts +2 -2
- package/src/compiled.ts +13 -15
- package/src/macros/env.ts +0 -4
- package/CLAUDE.md +0 -111
- package/PLAN.md +0 -274
- package/biome.jsonc +0 -1
- package/bun.lock +0 -98
- package/fixtures/openapi-array-items.json +0 -22
- package/fixtures/openapi-auth.json +0 -34
- package/fixtures/openapi-body.json +0 -41
- package/fixtures/openapi-collision.json +0 -21
- package/fixtures/openapi-oauth.json +0 -54
- package/fixtures/openapi-servers.json +0 -35
- package/fixtures/openapi.json +0 -87
- package/scripts/smoke-specs.ts +0 -64
- package/src/cli/auth-requirements.test.ts +0 -27
- package/src/cli/auth-schemes.test.ts +0 -66
- package/src/cli/capabilities.test.ts +0 -94
- package/src/cli/command-id.test.ts +0 -32
- package/src/cli/command-model.test.ts +0 -44
- package/src/cli/naming.test.ts +0 -86
- package/src/cli/operations.test.ts +0 -57
- package/src/cli/params.test.ts +0 -70
- package/src/cli/positional.test.ts +0 -65
- package/src/cli/request-body.test.ts +0 -35
- package/src/cli/runtime/request.test.ts +0 -153
- package/src/cli/server.test.ts +0 -35
- package/tsconfig.json +0 -29
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
|
|
5
|
-
import type { CommandAction } from "../command-model.ts";
|
|
6
|
-
|
|
7
|
-
import { buildRequest } from "./request.ts";
|
|
8
|
-
import { createAjv, formatAjvErrors } from "./validate/index.ts";
|
|
9
|
-
|
|
10
|
-
function makeAction(partial?: Partial<CommandAction>): CommandAction {
|
|
11
|
-
return {
|
|
12
|
-
id: "test",
|
|
13
|
-
key: "POST /contacts",
|
|
14
|
-
action: "create",
|
|
15
|
-
pathArgs: [],
|
|
16
|
-
method: "POST",
|
|
17
|
-
path: "/contacts",
|
|
18
|
-
tags: [],
|
|
19
|
-
style: "rest",
|
|
20
|
-
positionals: [],
|
|
21
|
-
flags: [],
|
|
22
|
-
params: [],
|
|
23
|
-
auth: { alternatives: [] },
|
|
24
|
-
requestBody: {
|
|
25
|
-
required: true,
|
|
26
|
-
content: [
|
|
27
|
-
{
|
|
28
|
-
contentType: "application/json",
|
|
29
|
-
required: true,
|
|
30
|
-
schemaType: "object",
|
|
31
|
-
},
|
|
32
|
-
],
|
|
33
|
-
hasJson: true,
|
|
34
|
-
hasFormUrlEncoded: false,
|
|
35
|
-
hasMultipart: false,
|
|
36
|
-
bodyFlags: ["--data", "--file"],
|
|
37
|
-
preferredContentType: "application/json",
|
|
38
|
-
preferredSchema: undefined,
|
|
39
|
-
},
|
|
40
|
-
requestBodySchema: {
|
|
41
|
-
type: "object",
|
|
42
|
-
properties: {
|
|
43
|
-
name: { type: "string" },
|
|
44
|
-
},
|
|
45
|
-
required: ["name"],
|
|
46
|
-
},
|
|
47
|
-
...partial,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
describe("buildRequest (requestBody)", () => {
|
|
52
|
-
test("builds body from expanded --body-* flags", async () => {
|
|
53
|
-
const prevHome = process.env.HOME;
|
|
54
|
-
const home = `${tmpdir()}/opencli-test-${crypto.randomUUID()}`;
|
|
55
|
-
process.env.HOME = home;
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
const { request, curl } = await buildRequest({
|
|
59
|
-
specId: "spec",
|
|
60
|
-
action: makeAction(),
|
|
61
|
-
positionalValues: [],
|
|
62
|
-
flagValues: { __body: { bodyName: "A" } },
|
|
63
|
-
globals: {},
|
|
64
|
-
servers: [
|
|
65
|
-
{ url: "https://api.example.com", variables: [], variableNames: [] },
|
|
66
|
-
],
|
|
67
|
-
authSchemes: [],
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
expect(request.headers.get("Content-Type")).toBe("application/json");
|
|
71
|
-
expect(await request.clone().text()).toBe('{"name":"A"}');
|
|
72
|
-
expect(curl).toContain("--data");
|
|
73
|
-
expect(curl).toContain('{"name":"A"}');
|
|
74
|
-
} finally {
|
|
75
|
-
process.env.HOME = prevHome;
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test("throws when requestBody is required but missing", async () => {
|
|
80
|
-
const prevHome = process.env.HOME;
|
|
81
|
-
const home = `${tmpdir()}/opencli-test-${crypto.randomUUID()}`;
|
|
82
|
-
process.env.HOME = home;
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
await expect(() =>
|
|
86
|
-
buildRequest({
|
|
87
|
-
specId: "spec",
|
|
88
|
-
action: makeAction(),
|
|
89
|
-
positionalValues: [],
|
|
90
|
-
flagValues: {},
|
|
91
|
-
globals: {},
|
|
92
|
-
servers: [
|
|
93
|
-
{
|
|
94
|
-
url: "https://api.example.com",
|
|
95
|
-
variables: [],
|
|
96
|
-
variableNames: [],
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
authSchemes: [],
|
|
100
|
-
}),
|
|
101
|
-
).toThrow(
|
|
102
|
-
"Missing request body. Provide --data, --file, or --body-* flags.",
|
|
103
|
-
);
|
|
104
|
-
} finally {
|
|
105
|
-
process.env.HOME = prevHome;
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test("throws friendly error for missing required expanded field", async () => {
|
|
110
|
-
const prevHome = process.env.HOME;
|
|
111
|
-
const home = `${tmpdir()}/opencli-test-${crypto.randomUUID()}`;
|
|
112
|
-
process.env.HOME = home;
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
await expect(() =>
|
|
116
|
-
buildRequest({
|
|
117
|
-
specId: "spec",
|
|
118
|
-
action: makeAction(),
|
|
119
|
-
positionalValues: [],
|
|
120
|
-
flagValues: { __body: { bodyFoo: "bar" } },
|
|
121
|
-
globals: {},
|
|
122
|
-
servers: [
|
|
123
|
-
{
|
|
124
|
-
url: "https://api.example.com",
|
|
125
|
-
variables: [],
|
|
126
|
-
variableNames: [],
|
|
127
|
-
},
|
|
128
|
-
],
|
|
129
|
-
authSchemes: [],
|
|
130
|
-
}),
|
|
131
|
-
).toThrow(
|
|
132
|
-
"Missing required body field 'name'. Provide --body-name or use --data/--file.",
|
|
133
|
-
);
|
|
134
|
-
} finally {
|
|
135
|
-
process.env.HOME = prevHome;
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
describe("formatAjvErrors", () => {
|
|
141
|
-
test("pretty prints required errors", () => {
|
|
142
|
-
const ajv = createAjv();
|
|
143
|
-
const validate = ajv.compile({
|
|
144
|
-
type: "object",
|
|
145
|
-
properties: { name: { type: "string" } },
|
|
146
|
-
required: ["name"],
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
validate({});
|
|
150
|
-
const msg = formatAjvErrors(validate.errors);
|
|
151
|
-
expect(msg).toBe("/ missing required property 'name'");
|
|
152
|
-
});
|
|
153
|
-
});
|
package/src/cli/server.test.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
|
|
3
|
-
import { listServers } from "./server.ts";
|
|
4
|
-
import type { OpenApiDoc } from "./types.ts";
|
|
5
|
-
|
|
6
|
-
describe("listServers", () => {
|
|
7
|
-
test("extracts server variables from template", () => {
|
|
8
|
-
const doc: OpenApiDoc = {
|
|
9
|
-
openapi: "3.0.3",
|
|
10
|
-
servers: [
|
|
11
|
-
{
|
|
12
|
-
url: "https://{region}.api.example.com/{basePath}",
|
|
13
|
-
variables: {
|
|
14
|
-
region: {
|
|
15
|
-
default: "us",
|
|
16
|
-
enum: ["us", "eu"],
|
|
17
|
-
},
|
|
18
|
-
basePath: {
|
|
19
|
-
default: "v1",
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
} as const,
|
|
23
|
-
],
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const servers = listServers(doc);
|
|
27
|
-
expect(servers).toHaveLength(1);
|
|
28
|
-
expect(servers[0]?.variableNames).toEqual(["region", "basePath"]);
|
|
29
|
-
expect(servers[0]?.variables.map((v) => v.name)).toEqual([
|
|
30
|
-
"region",
|
|
31
|
-
"basePath",
|
|
32
|
-
]);
|
|
33
|
-
expect(servers[0]?.variables[0]?.enum).toEqual(["us", "eu"]);
|
|
34
|
-
});
|
|
35
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
// Environment setup & latest features
|
|
4
|
-
"lib": ["ESNext"],
|
|
5
|
-
"target": "ESNext",
|
|
6
|
-
"module": "Preserve",
|
|
7
|
-
"moduleDetection": "force",
|
|
8
|
-
"jsx": "react-jsx",
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
|
|
11
|
-
// Bundler mode
|
|
12
|
-
"moduleResolution": "bundler",
|
|
13
|
-
"allowImportingTsExtensions": true,
|
|
14
|
-
"verbatimModuleSyntax": true,
|
|
15
|
-
"noEmit": true,
|
|
16
|
-
|
|
17
|
-
// Best practices
|
|
18
|
-
"strict": true,
|
|
19
|
-
"skipLibCheck": true,
|
|
20
|
-
"noFallthroughCasesInSwitch": true,
|
|
21
|
-
"noUncheckedIndexedAccess": true,
|
|
22
|
-
"noImplicitOverride": true,
|
|
23
|
-
|
|
24
|
-
// Some stricter flags (disabled by default)
|
|
25
|
-
"noUnusedLocals": false,
|
|
26
|
-
"noUnusedParameters": false,
|
|
27
|
-
"noPropertyAccessFromIndexSignature": false
|
|
28
|
-
}
|
|
29
|
-
}
|