@oprt/cli 0.1.0 → 0.3.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.
package/dist/index.d.cts CHANGED
@@ -1,37 +1,144 @@
1
- import { C as Command, a as Contract, R as Registry, b as RegistryEntry, A as AddOptions, I as InstallResult } from './read-8a9euzJx.cjs';
2
- export { c as CliError, d as ComponentDetail, D as DetailProp, e as IndexEntry, f as InstallFile, S as SearchResult, g as applyBlock, h as blockVersion, i as componentDetail, j as componentIndex, r as removeBlock, k as renderAgentBlock, l as renderComponent, s as search } from './read-8a9euzJx.cjs';
1
+ import { C as Contract, a as ComponentDetail, b as Command, R as Registry, c as RegistryEntry, A as AddOptions, I as InstallResult } from './read-C7rE5UlY.cjs';
2
+ export { d as CliError, D as DetailProp, e as IndexEntry, f as InstallFile, S as SearchResult, g as applyBlock, h as blockVersion, i as componentDetail, j as componentIndex, r as removeBlock, k as renderAgentBlock, l as renderComponent, s as search } from './read-C7rE5UlY.cjs';
3
3
 
4
- /** The envelope every `--json` answer comes in. `type` says what `data` holds. */
5
- interface Envelope {
4
+ /** This program's version: the package's. The contract has its own (`Contract.version`). */
5
+ declare const VERSION: string;
6
+ /**
7
+ * The version of the result model: the envelope and the data of every `--json` answer and MCP
8
+ * structured result. It rises when a field is removed or changes meaning; adding a field does not
9
+ * raise it. The envelope's `apiVersion` is the same number, kept for the readers that branch on it.
10
+ */
11
+ declare const RESULT_SCHEMA_VERSION = 1;
12
+ interface Identity {
13
+ /** This program: the `@oprt/cli` package version. */
14
+ cli_version: string;
15
+ /** The contract it carries: the `@oprt/react` version the contract describes. */
16
+ contract_version: string;
17
+ /**
18
+ * `sha256:` and the hash of the contract as `dist/contract.json` holds it (the file's bytes, so
19
+ * `shasum -a 256 dist/contract.json` gives the same). Two answers with one digest read one contract.
20
+ */
21
+ contract_digest: string;
22
+ /** The result model's version. */
23
+ schema_version: number;
24
+ }
25
+ /** What an answer can say about itself when the contract could not be read. */
26
+ interface ErrorIdentity {
27
+ cli_version: string;
28
+ schema_version: number;
29
+ contract_version?: string;
30
+ contract_digest?: string;
31
+ }
32
+ /** The contract's digest. Computed once per contract: it is one hash of about 160 KB. */
33
+ declare function contractDigest(contract: Contract): string;
34
+ declare function identityOf(contract: Contract): Identity;
35
+
36
+ /**
37
+ * The `typescript` module as the project has it. It is opaque in the installer's own types, so
38
+ * that using those types does not require TypeScript to be installed.
39
+ */
40
+ type TypeScript = object;
41
+ /** Where the parser came from, for a person or an agent deciding whether to trust the answer. */
42
+ interface ParserInfo {
43
+ name: "typescript";
44
+ version: string;
45
+ /**
46
+ * `project`: resolved from the directory being checked. `installer`: found beside this program
47
+ * instead, because the project has none of its own. `provided`: handed in by a caller of the
48
+ * library.
49
+ */
50
+ source: "project" | "installer" | "provided";
51
+ }
52
+ interface ParserResolution extends ParserInfo {
53
+ /** The folder of the `typescript` package that was loaded. */
54
+ resolved_from: string;
55
+ }
56
+ /** Why checking cannot run, as a stable word. */
57
+ type ParserBlock = "typescript_missing" | "typescript_unusable";
58
+ type ParserProbe = {
59
+ ready: true;
60
+ typescript: TypeScript;
61
+ resolution: ParserResolution;
62
+ } | {
63
+ ready: false;
64
+ reason: ParserBlock;
65
+ detail: string;
66
+ };
67
+
68
+ declare const RESULT_TYPES: readonly ["check", "search", "component.detail", "component.batch", "component.list", "init", "doctor", "add", "list", "instructions"];
69
+ type ResultType = (typeof RESULT_TYPES)[number];
70
+ /** The envelope every `--json` answer and every structured tool result comes in. */
71
+ interface Envelope<T = unknown> {
72
+ /** The result model's version (same number as `identity.schema_version`), for readers that branch on it. */
6
73
  apiVersion: 1;
7
- type: string;
8
- data: unknown;
74
+ /** What `data` holds. */
75
+ type: ResultType;
76
+ identity: Identity;
77
+ data: T;
9
78
  }
79
+ /** What a failure comes in. `code` is stable and only ever added to. */
80
+ interface ErrorEnvelope {
81
+ apiVersion: 1;
82
+ error: string;
83
+ code: string;
84
+ suggestions?: string[];
85
+ identity: ErrorIdentity;
86
+ }
87
+ declare const envelope: <T>(type: ResultType, data: T, contract: Contract) => Envelope<T>;
88
+ /**
89
+ * A failure as the model carries it. The contract is optional: a failure can come before the
90
+ * contract was read, and the answer still says which program it came from.
91
+ */
92
+ declare function errorEnvelope(error: unknown, contract?: Contract): ErrorEnvelope;
93
+ type ComponentDetailData = Omit<ComponentDetail, "description"> & {
94
+ /** Absent from the compact form. */
95
+ description?: string;
96
+ /** True for the compact form: no component description, one sentence per prop. */
97
+ dense: boolean;
98
+ };
99
+ type Schema = Record<string, unknown>;
100
+ /** The schema of one kind of answer: `schemaFor("check")`, or `schemaFor("error")` for a failure. */
101
+ declare function schemaFor(type: ResultType | "error"): Schema;
102
+ /**
103
+ * The schema an MCP tool declares as its `outputSchema`: one object that is either the answer for
104
+ * its type (`type` and `data`) or the failure (`error` and `code`), since a tool that could not
105
+ * run returns the failure in the same place, and the client checks structured content whether or
106
+ * not the call failed. One object with two ways to be complete is smaller than two schemas under
107
+ * `anyOf`, which repeated the envelope in every tool.
108
+ */
109
+ declare function outputSchemaFor(type: ResultType): Schema;
110
+ /** Every schema, by name: what the library exports for a client that wants to check an answer. */
111
+ declare const RESULT_SCHEMAS: Readonly<Record<ResultType | "error", Schema>>;
112
+
10
113
  interface Answer {
11
114
  /** What a person reads. */
12
115
  text: string;
13
- /** What `--json` prints. */
116
+ /** What `--json` prints: the result model, the same object an MCP tool returns. */
14
117
  json: Envelope;
15
118
  exitCode: number;
16
119
  }
17
120
  type AgentCommand = Extract<Command, {
18
- command: "component" | "search" | "init" | "doctor" | "check";
121
+ command: "component" | "search" | "init" | "doctor" | "check" | "list" | "add";
19
122
  }>;
20
- /** Runs one of the commands an agent reads the contract with, and returns both forms of the answer. */
123
+ /**
124
+ * Runs one of the commands that answers with data, and returns both forms of the answer: the text a
125
+ * person reads and the envelope `--json` prints. The MCP server builds its structured results from
126
+ * the same functions, so the two cannot disagree.
127
+ */
21
128
  declare function runAgentCommand(command: AgentCommand, context: {
22
129
  cwd: string;
23
130
  contract: Contract;
24
131
  registry: Registry;
132
+ /** For doctor: the TypeScript resolution to report, when the caller already has it. */
133
+ parser?: ParserProbe;
25
134
  }): Answer;
26
135
 
27
- /**
28
- * The `typescript` module as the project has it. It is opaque in the installer's own types, so
29
- * that using those types does not require TypeScript to be installed.
30
- */
31
- type TypeScript = object;
136
+ /** Every code a finding can carry. Stable, and only ever added to: branch on these, not on messages. */
137
+ declare const FINDING_CODES: readonly ["INVALID_PROP_VALUE", "UNKNOWN_EXPORT", "DOT_NOTATION", "INVALID_NESTING", "INVALID_CHILD", "MISSING_REQUIRED_PROP", "UNKNOWN_PROP", "RAW_COLOR", "ARBITRARY_SIZE", "ROUNDED_CORNER", "NATIVE_CONTROL", "SYNTAX_ERROR"];
138
+ declare const LIMITATION_CODES: readonly ["UNRESOLVED_SPREAD", "UNRESOLVED_VALUE"];
32
139
  interface Finding {
33
140
  /** Stable, and only ever added to. Branch on this, not on the message. */
34
- code: "INVALID_PROP_VALUE" | "UNKNOWN_EXPORT" | "DOT_NOTATION" | "INVALID_NESTING" | "INVALID_CHILD" | "MISSING_REQUIRED_PROP" | "UNKNOWN_PROP" | "RAW_COLOR" | "ARBITRARY_SIZE" | "ROUNDED_CORNER" | "NATIVE_CONTROL";
141
+ code: (typeof FINDING_CODES)[number];
35
142
  /** An error breaks the contract. A warning breaks a house rule, or may be a native attribute. */
36
143
  severity: "error" | "warning";
37
144
  file: string;
@@ -43,17 +150,92 @@ interface Finding {
43
150
  valid_values?: string[];
44
151
  suggestions?: string[];
45
152
  }
153
+ /**
154
+ * Something the check could not read, so it did not judge it. Recorded with its place, never
155
+ * guessed: the code may be right or wrong there, and this says only that it was not looked at.
156
+ */
157
+ interface Limitation {
158
+ /** Stable, and only ever added to. */
159
+ code: (typeof LIMITATION_CODES)[number];
160
+ file: string;
161
+ line: number;
162
+ column: number;
163
+ component: string;
164
+ prop?: string;
165
+ message: string;
166
+ }
167
+ /**
168
+ * What happened to one file. `evaluated`: read in full. `partial`: checked, with limits the
169
+ * report records. `not_evaluated`: it does not parse, so nothing about the contract was checked.
170
+ */
171
+ interface SourceEvaluation {
172
+ file: string;
173
+ status: "evaluated" | "partial" | "not_evaluated";
174
+ findings: Finding[];
175
+ limitations: Limitation[];
176
+ }
177
+ type EvaluationStatus = "evaluated_clean" | "evaluated_with_findings" | "partially_evaluated" | "not_evaluated" | "no_files_evaluated";
178
+ /** An input that was named but not read, and why. */
179
+ interface SkippedInput {
180
+ path: string;
181
+ reason: "unsupported_extension" | "test_or_story_file" | "excluded_folder";
182
+ }
46
183
  interface CheckReport {
47
- /** How many files were read. */
184
+ /**
185
+ * `evaluated_clean` means every file was read in full and nothing was found. Anything less is
186
+ * named: findings, limits, files that did not parse, or no file read at all.
187
+ */
188
+ evaluation_status: EvaluationStatus;
189
+ /** How many files were read (found and opened). */
48
190
  files: number;
49
191
  findings: Finding[];
50
192
  summary: {
51
193
  errors: number;
52
194
  warnings: number;
53
195
  };
196
+ coverage: {
197
+ files_found: number;
198
+ /** Parsed and checked, including those with limits. */
199
+ files_evaluated: number;
200
+ /** Of those evaluated, the ones with a limit. */
201
+ files_partial: number;
202
+ /** Did not parse. */
203
+ files_not_evaluated: number;
204
+ };
205
+ /** Everything that was not read, each with its place. Empty only when nothing was skipped over. */
206
+ limitations: Limitation[];
207
+ /** Inputs that were named and not read, with the reason. */
208
+ skipped_inputs: SkippedInput[];
209
+ /** What this check covers, and what it leaves to other tools. The same on every run. */
210
+ scope: {
211
+ checked: string[];
212
+ not_checked: string[];
213
+ };
214
+ parser: ParserInfo;
54
215
  }
55
- /** Check one file's source. `file` is only the name the findings carry. */
56
- declare function checkSource(typescript: TypeScript, contract: Contract, file: string, text: string): Finding[];
216
+ /**
217
+ * Check one file's source. `file` is only the name the findings carry. A file that does not parse
218
+ * is not checked at all (`not_evaluated`, with the syntax errors as findings): what TypeScript
219
+ * recovers from broken code is a guess, and the contract is not judged on a guess.
220
+ */
221
+ declare function checkSource(typescript: TypeScript, contract: Contract, file: string, text: string): SourceEvaluation;
222
+ /**
223
+ * The report for a set of evaluated files. The status is `evaluated_clean` only when every file
224
+ * was read in full and nothing was found; everything short of that has its own name.
225
+ */
226
+ declare function buildCheckReport(evaluations: readonly SourceEvaluation[], context: {
227
+ parser: ParserInfo;
228
+ skipped?: SkippedInput[];
229
+ }): CheckReport;
230
+ /**
231
+ * The exit code of `oprt check`. 0: every file that was read has no errors (and, when strict, no
232
+ * warnings); limits are shown and do not fail the run. 1: an error was found, a file did not
233
+ * parse, or no file was read at all (nothing was checked, which is not a pass). Usage mistakes
234
+ * and a path that is not there exit 2, and a missing TypeScript exits 1, before any report.
235
+ */
236
+ declare function checkExitCode(report: CheckReport, { strict }: {
237
+ strict: boolean;
238
+ }): number;
57
239
  /**
58
240
  * Check every .tsx and .jsx file under the given paths. `typescript` is found in the project when
59
241
  * it is not passed; null stands for "there is none".
@@ -63,6 +245,11 @@ declare function checkPaths(paths: string[], context: {
63
245
  contract: Contract;
64
246
  typescript?: TypeScript | null;
65
247
  }): CheckReport;
248
+ /**
249
+ * A check as text, for a terminal or a tool result. Findings first, then the limits, then one
250
+ * line that says how much was read: the same words the JSON status carries.
251
+ */
252
+ declare function renderCheckText(report: CheckReport): string;
66
253
 
67
254
  interface DoctorCheck {
68
255
  id: string;
@@ -70,7 +257,31 @@ interface DoctorCheck {
70
257
  message: string;
71
258
  fix?: string;
72
259
  }
260
+ /**
261
+ * Whether one thing oprt does can run here. Lookups (search, component, list) read the contract
262
+ * that ships inside oprt, so they always can. Checking code needs a parser, which is the
263
+ * project's own TypeScript: without it that operation is blocked, with the reason as a word.
264
+ */
265
+ interface DoctorOperations {
266
+ lookup: {
267
+ status: "ready";
268
+ message: string;
269
+ contract_version: string;
270
+ };
271
+ check_code: {
272
+ status: "ready" | "blocked";
273
+ message: string;
274
+ reason?: ParserBlock;
275
+ fix?: string;
276
+ /** The parser that checking will use, when it is ready. */
277
+ typescript?: Pick<ParserResolution, "version" | "resolved_from" | "source">;
278
+ };
279
+ }
73
280
  interface DoctorReport {
281
+ /** The directory every answer here is about: where the project's packages are looked for. */
282
+ consumer_directory: string;
283
+ /** What can run here, one operation at a time. */
284
+ operations: DoctorOperations;
74
285
  checks: DoctorCheck[];
75
286
  summary: {
76
287
  ok: number;
@@ -78,11 +289,31 @@ interface DoctorReport {
78
289
  fail: number;
79
290
  };
80
291
  }
81
- declare function doctor({ cwd, contract }: {
292
+ declare function doctor({ cwd, contract, parser, }: {
82
293
  cwd: string;
83
294
  contract: Contract;
295
+ /** What resolving TypeScript from `cwd` found. Resolved here when it is not passed. */
296
+ parser?: ParserProbe;
84
297
  }): DoctorReport;
85
298
 
299
+ interface InputSchema {
300
+ type: "object";
301
+ properties: Record<string, PropertySchema>;
302
+ required?: string[];
303
+ additionalProperties?: boolean;
304
+ description?: string;
305
+ }
306
+ interface PropertySchema {
307
+ type: "string" | "number" | "integer" | "boolean";
308
+ description?: string;
309
+ default?: unknown;
310
+ enum?: unknown[];
311
+ minimum?: number;
312
+ maximum?: number;
313
+ minLength?: number;
314
+ maxLength?: number;
315
+ }
316
+
86
317
  interface McpContext {
87
318
  contract: Contract;
88
319
  registry: Registry;
@@ -90,78 +321,17 @@ interface McpContext {
90
321
  typescript?: TypeScript | null;
91
322
  cwd?: string;
92
323
  }
93
- declare const TOOLS: ({
324
+ interface ToolDefinition {
94
325
  name: string;
95
326
  description: string;
96
- inputSchema: {
97
- type: string;
98
- properties: {
99
- query: {
100
- type: string;
101
- description: string;
102
- };
103
- limit: {
104
- type: string;
105
- description: string;
106
- };
107
- name?: never;
108
- dense?: never;
109
- code?: never;
110
- };
111
- required: string[];
327
+ inputSchema: InputSchema;
328
+ /** The result model for this tool's answers; a failure comes in the same place. */
329
+ outputSchema: object;
330
+ annotations: {
331
+ readOnlyHint: true;
112
332
  };
113
- } | {
114
- name: string;
115
- description: string;
116
- inputSchema: {
117
- type: string;
118
- properties: {
119
- name: {
120
- type: string;
121
- description: string;
122
- };
123
- dense: {
124
- type: string;
125
- description: string;
126
- };
127
- query?: never;
128
- limit?: never;
129
- code?: never;
130
- };
131
- required: string[];
132
- };
133
- } | {
134
- name: string;
135
- description: string;
136
- inputSchema: {
137
- type: string;
138
- properties: {
139
- query?: never;
140
- limit?: never;
141
- name?: never;
142
- dense?: never;
143
- code?: never;
144
- };
145
- required?: never;
146
- };
147
- } | {
148
- name: string;
149
- description: string;
150
- inputSchema: {
151
- type: string;
152
- properties: {
153
- code: {
154
- type: string;
155
- description: string;
156
- };
157
- query?: never;
158
- limit?: never;
159
- name?: never;
160
- dense?: never;
161
- };
162
- required: string[];
163
- };
164
- })[];
333
+ }
334
+ declare const TOOLS: readonly ToolDefinition[];
165
335
  /**
166
336
  * Answer one message. Returns the response to write, or null for a notification, which gets none.
167
337
  * `raw` is a parsed message, or the line itself when it could not be parsed.
@@ -197,7 +367,6 @@ declare function parseArgs(args: string[]): Command;
197
367
 
198
368
  declare function resolveEntries(names: string[], registry: Registry): RegistryEntry[];
199
369
 
200
- declare const VERSION: string;
201
370
  declare const registry: Registry;
202
371
  /** The contract this installer carries, read from beside it the first time it is asked for. */
203
372
  declare const contract: () => Contract;
@@ -208,4 +377,4 @@ declare function install(options: AddOptions, context?: {
208
377
  registry?: Registry;
209
378
  }): InstallResult;
210
379
 
211
- export { AddOptions, type Answer, type CheckReport, Command, Contract, DEFAULT_OUT, type DoctorCheck, type DoctorReport, type Envelope, type Finding, type InitFile, type InitOptions, type InitResult, InstallResult, type McpContext, Registry, RegistryEntry, TOOLS, type TypeScript, VERSION, checkPaths, checkSource, contract, doctor, handleMessage, init, install, parseArgs, registry, resolveEntries, runAgentCommand, serve };
380
+ export { AddOptions, type Answer, type CheckReport, Command, ComponentDetail, type ComponentDetailData, Contract, DEFAULT_OUT, type DoctorCheck, type DoctorReport, type Envelope, type ErrorEnvelope, type ErrorIdentity, type EvaluationStatus, type Finding, type Identity, type InitFile, type InitOptions, type InitResult, InstallResult, type Limitation, type McpContext, RESULT_SCHEMAS, RESULT_SCHEMA_VERSION, RESULT_TYPES, Registry, RegistryEntry, type ResultType, type SkippedInput, type SourceEvaluation, TOOLS, type TypeScript, VERSION, buildCheckReport, checkExitCode, checkPaths, checkSource, contract, contractDigest, doctor, envelope, errorEnvelope, handleMessage, identityOf, init, install, outputSchemaFor, parseArgs, registry, renderCheckText, resolveEntries, runAgentCommand, schemaFor, serve };