@azure-tools/typespec-azure-examples 0.1.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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -0
  3. package/dist/schema/dist/ExamplesYaml.json +111 -0
  4. package/dist/src/cli.d.ts +3 -0
  5. package/dist/src/cli.d.ts.map +1 -0
  6. package/dist/src/cli.js +23 -0
  7. package/dist/src/cli.js.map +1 -0
  8. package/dist/src/commands/validate.d.ts +9 -0
  9. package/dist/src/commands/validate.d.ts.map +1 -0
  10. package/dist/src/commands/validate.js +37 -0
  11. package/dist/src/commands/validate.js.map +1 -0
  12. package/dist/src/discover.d.ts +20 -0
  13. package/dist/src/discover.d.ts.map +1 -0
  14. package/dist/src/discover.js +73 -0
  15. package/dist/src/discover.js.map +1 -0
  16. package/dist/src/index.d.ts +14 -0
  17. package/dist/src/index.d.ts.map +1 -0
  18. package/dist/src/index.js +13 -0
  19. package/dist/src/index.js.map +1 -0
  20. package/dist/src/loader.d.ts +41 -0
  21. package/dist/src/loader.d.ts.map +1 -0
  22. package/dist/src/loader.js +70 -0
  23. package/dist/src/loader.js.map +1 -0
  24. package/dist/src/naming.d.ts +17 -0
  25. package/dist/src/naming.d.ts.map +1 -0
  26. package/dist/src/naming.js +26 -0
  27. package/dist/src/naming.js.map +1 -0
  28. package/dist/src/reporter.d.ts +6 -0
  29. package/dist/src/reporter.d.ts.map +1 -0
  30. package/dist/src/reporter.js +27 -0
  31. package/dist/src/reporter.js.map +1 -0
  32. package/dist/src/rules.d.ts +18 -0
  33. package/dist/src/rules.d.ts.map +1 -0
  34. package/dist/src/rules.js +188 -0
  35. package/dist/src/rules.js.map +1 -0
  36. package/dist/src/schema.d.ts +3 -0
  37. package/dist/src/schema.d.ts.map +1 -0
  38. package/dist/src/schema.js +5 -0
  39. package/dist/src/schema.js.map +1 -0
  40. package/dist/src/types.d.ts +49 -0
  41. package/dist/src/types.d.ts.map +1 -0
  42. package/dist/src/types.js +6 -0
  43. package/dist/src/types.js.map +1 -0
  44. package/dist/src/validate.d.ts +11 -0
  45. package/dist/src/validate.d.ts.map +1 -0
  46. package/dist/src/validate.js +66 -0
  47. package/dist/src/validate.js.map +1 -0
  48. package/dist/tsconfig.build.tsbuildinfo +1 -0
  49. package/package.json +69 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Microsoft Corporation. All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE
package/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # @azure-tools/typespec-azure-examples
2
+
3
+ Tooling for the Azure **unified examples format** (`examples.yaml`): the published JSON Schema
4
+ and the `tsp-examples` CLI.
5
+
6
+ The unified examples format replaces the ~282K per-version `x-ms-examples` JSON files with a
7
+ single version-aware `examples.yaml` per service (or `examples/<Interface>.yaml` for large
8
+ services). See the RFC: _Unified Examples Format_.
9
+
10
+ ## Format
11
+
12
+ ```yaml
13
+ $schema: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/schemas/examples.schema.yaml
14
+ $namespace: Microsoft.EventGrid
15
+
16
+ CaCertificates.get:
17
+ - request:
18
+ path:
19
+ subscriptionId: 8f6b6269-84f2-4d09-9e31-1127efcd1e40
20
+ resourceGroupName: myResourceGroup
21
+ responses:
22
+ 200:
23
+ body:
24
+ name: exampleCaCertificate
25
+ properties:
26
+ provisioningState: Succeeded
27
+ - since: "2023-12-15-preview"
28
+ request:
29
+ path:
30
+ subscriptionId: 8f6b6269-84f2-4d09-9e31-1127efcd1e40
31
+ resourceGroupName: myResourceGroup
32
+ responses:
33
+ 200:
34
+ body:
35
+ name: exampleCaCertificate
36
+ properties:
37
+ provisioningState: Succeeded
38
+ delegatedIdentityTokenExpirationTimeInUtc: "2023-10-12T23:06:43+00:00"
39
+ ```
40
+
41
+ - File metadata uses `$`-prefixed keys (`$schema`, `$namespace`); every bare top-level key is an
42
+ operation, identified by its interface-relative name (`Interface.operation`).
43
+ - Each operation maps to a list of example variants. The base variant has no `since`; later
44
+ variants carry a quoted `since` and restate the full request/response.
45
+ - Response status codes are bare integer keys. `api-version` is implicit; use the
46
+ `{api-version}` placeholder where a version must be embedded in a value.
47
+
48
+ ## `tsp-examples validate`
49
+
50
+ Validate a service's example files against the JSON Schema and the format rules:
51
+
52
+ ```bash
53
+ tsp-examples validate <service-dir>
54
+ ```
55
+
56
+ It discovers `examples.yaml` and `examples/*.yaml` in the directory, reads the adjacent
57
+ `service.yaml` for version metadata, and reports diagnostics. It exits non-zero if any error is
58
+ found (use `--warn-as-error` to also fail on warnings).
59
+
60
+ ### Rules enforced
61
+
62
+ - Only `$schema`/`$namespace` may be `$`-prefixed; other bare keys are operations that must be a
63
+ list of examples.
64
+ - Response keys are integer status codes; range keys (`2XX`) and `default` are rejected.
65
+ - `since` must be a quoted string and a version listed in `service.yaml`.
66
+ - Per lineage (entries grouped by `title`; untitled entries form the default lineage): at most one
67
+ entry without `since`, and `since` values are unique.
68
+ - An operation's full example set lives in a single file, and each interface appears in exactly
69
+ one file.
70
+ - `{api-version}` is the only supported placeholder, and `api-version` must not appear as a
71
+ request parameter.
72
+
73
+ ## API
74
+
75
+ ```ts
76
+ import {
77
+ validateExamplesDir,
78
+ validateExampleFiles,
79
+ loadExampleFile,
80
+ } from "@azure-tools/typespec-azure-examples";
81
+
82
+ const { diagnostics } = await validateExamplesDir("path/to/service");
83
+ ```
@@ -0,0 +1,111 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "examples.yaml",
4
+ "type": "object",
5
+ "properties": {
6
+ "$schema": {
7
+ "type": "string",
8
+ "description": "Schema URL. Gives editors autocomplete and inline validation while authoring."
9
+ },
10
+ "$namespace": {
11
+ "type": "string",
12
+ "description": "Service namespace (e.g. `Microsoft.EventGrid`), prepended to each operation key to form\nthe fully-qualified operation identity used for Swagger linkage (`x-id`)."
13
+ }
14
+ },
15
+ "unevaluatedProperties": {
16
+ "anyOf": [
17
+ {
18
+ "type": "array",
19
+ "items": {
20
+ "$ref": "#/$defs/Example"
21
+ }
22
+ },
23
+ {
24
+ "type": "string"
25
+ }
26
+ ]
27
+ },
28
+ "description": "Top-level `examples.yaml` file: `$schema`/`$namespace` metadata plus one entry per\noperation, keyed by the interface-relative operation name (e.g. `CaCertificates.get`).\nEach operation maps to a list of example variants.\n\nThe indexer is widened to `Example[] | string` so the `$`-prefixed string metadata keys\nare structurally valid. The rules that a bare (non-`$`) key must be a list of examples and\nthat the only allowed metadata keys are `$schema`/`$namespace` are enforced by the\n`examples-validate` semantic rules.",
29
+ "$defs": {
30
+ "Example": {
31
+ "type": "object",
32
+ "properties": {
33
+ "title": {
34
+ "type": "string",
35
+ "description": "Optional human-readable title. Omit for the single-example case; provide it only to\ndisambiguate multiple distinct examples on the same operation. Entries sharing a `title`\nform one lineage; untitled entries all belong to the single default lineage."
36
+ },
37
+ "description": {
38
+ "type": "string",
39
+ "description": "Longer description of what this example demonstrates."
40
+ },
41
+ "legacyFilename": {
42
+ "type": "string",
43
+ "description": "Legacy `x-ms-examples` file name (e.g. `CaCertificates_Get.json`) this variant was migrated\nfrom. Preserved so an emitter can re-materialize the legacy file under its original name,\nkeeping the diff minimal during rollout. When omitted, the emitter derives the file name (and\nthe `x-ms-examples` key) from the operation id and `title`."
44
+ },
45
+ "since": {
46
+ "type": "string",
47
+ "description": "Quoted version from which this variant applies (must be a version listed in the service's\n`service.yaml`). Omit to apply from the earliest version."
48
+ },
49
+ "request": {
50
+ "$ref": "#/$defs/ExampleRequest",
51
+ "description": "The request of the API interaction."
52
+ },
53
+ "responses": {
54
+ "$ref": "#/$defs/RecordExampleResponse",
55
+ "description": "Responses keyed by integer status code (e.g. `200`, `404`)."
56
+ }
57
+ },
58
+ "required": [
59
+ "request",
60
+ "responses"
61
+ ],
62
+ "description": "A single example variant representing one complete API interaction."
63
+ },
64
+ "ExampleRequest": {
65
+ "type": "object",
66
+ "properties": {
67
+ "path": {
68
+ "$ref": "#/$defs/RecordUnknown",
69
+ "description": "Path parameters. `api-version` is implicit and MUST NOT be included."
70
+ },
71
+ "query": {
72
+ "$ref": "#/$defs/RecordUnknown",
73
+ "description": "Query parameters (e.g. `$top`, `$filter`)."
74
+ },
75
+ "headers": {
76
+ "$ref": "#/$defs/RecordUnknown",
77
+ "description": "Request headers (e.g. `If-Match`)."
78
+ },
79
+ "body": {
80
+ "description": "Request body. Structure matches the operation's request schema."
81
+ }
82
+ },
83
+ "description": "The request portion of an example, split by parameter location."
84
+ },
85
+ "RecordExampleResponse": {
86
+ "type": "object",
87
+ "properties": {},
88
+ "unevaluatedProperties": {
89
+ "$ref": "#/$defs/ExampleResponse"
90
+ }
91
+ },
92
+ "RecordUnknown": {
93
+ "type": "object",
94
+ "properties": {},
95
+ "unevaluatedProperties": {}
96
+ },
97
+ "ExampleResponse": {
98
+ "type": "object",
99
+ "properties": {
100
+ "headers": {
101
+ "$ref": "#/$defs/RecordUnknown",
102
+ "description": "Response headers (e.g. `Location`, `Azure-AsyncOperation`)."
103
+ },
104
+ "body": {
105
+ "description": "Response body. Structure matches the operation's response schema."
106
+ }
107
+ },
108
+ "description": "A single response of an example, keyed in the parent map by integer status code."
109
+ }
110
+ }
111
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable no-console */
3
+ import yargs from "yargs";
4
+ import { hideBin } from "yargs/helpers";
5
+ import { validateCommand } from "./commands/validate.js";
6
+ /**
7
+ * `tsp-examples` — the permanent CLI for the unified examples format. Sub-commands operate on a
8
+ * service's `examples.yaml` (`scaffold` and `add` are registered here as they land).
9
+ */
10
+ async function main() {
11
+ await yargs(hideBin(process.argv))
12
+ .scriptName("tsp-examples")
13
+ .command(validateCommand)
14
+ .demandCommand(1, "Specify a command (e.g. `validate`).")
15
+ .strict()
16
+ .help()
17
+ .parseAsync();
18
+ }
19
+ main().catch((error) => {
20
+ console.error(error);
21
+ process.exit(1);
22
+ });
23
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AACA,+BAA+B;AAC/B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD;;;GAGG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SAC/B,UAAU,CAAC,cAAc,CAAC;SAC1B,OAAO,CAAC,eAAe,CAAC;SACxB,aAAa,CAAC,CAAC,EAAE,sCAAsC,CAAC;SACxD,MAAM,EAAE;SACR,IAAI,EAAE;SACN,UAAU,EAAE,CAAC;AAClB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { CommandModule } from "yargs";
2
+ interface ValidateArgs {
3
+ dir: string;
4
+ "warn-as-error": boolean;
5
+ }
6
+ /** `tsp-examples validate` — validate the unified examples files in a service directory. */
7
+ export declare const validateCommand: CommandModule<unknown, ValidateArgs>;
8
+ export {};
9
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/commands/validate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAI3C,UAAU,YAAY;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,4FAA4F;AAC5F,eAAO,MAAM,eAAe,EAAE,aAAa,CAAC,OAAO,EAAE,YAAY,CAoChE,CAAC"}
@@ -0,0 +1,37 @@
1
+ /* eslint-disable no-console */
2
+ import { resolve } from "path";
3
+ import { validateExamplesDir } from "../discover.js";
4
+ import { formatDiagnostics, formatSummary } from "../reporter.js";
5
+ /** `tsp-examples validate` — validate the unified examples files in a service directory. */
6
+ export const validateCommand = {
7
+ command: "validate [dir]",
8
+ describe: "Validate unified examples format files (examples.yaml)",
9
+ builder: (yargs) => yargs
10
+ .positional("dir", {
11
+ type: "string",
12
+ describe: "Service directory containing examples.yaml / examples/*.yaml and service.yaml",
13
+ default: ".",
14
+ })
15
+ .option("warn-as-error", {
16
+ type: "boolean",
17
+ default: false,
18
+ describe: "Treat warnings as errors (non-zero exit)",
19
+ }),
20
+ handler: async (args) => {
21
+ const dir = resolve(process.cwd(), args.dir);
22
+ const { diagnostics, files } = await validateExamplesDir(dir);
23
+ if (files.length === 0) {
24
+ console.error(`No examples files found in ${dir} (looked for examples.yaml and examples/*.yaml).`);
25
+ process.exit(1);
26
+ }
27
+ if (diagnostics.length > 0) {
28
+ console.log(formatDiagnostics(diagnostics));
29
+ console.log("");
30
+ }
31
+ console.log(formatSummary(diagnostics));
32
+ const hasError = diagnostics.some((d) => d.severity === "error");
33
+ const hasWarning = diagnostics.some((d) => d.severity === "warning");
34
+ process.exit(hasError || (args["warn-as-error"] && hasWarning) ? 1 : 0);
35
+ },
36
+ };
37
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAOlE,4FAA4F;AAC5F,MAAM,CAAC,MAAM,eAAe,GAAyC;IACnE,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,wDAAwD;IAClE,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,KAAK,EAAE;QACjB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,+EAA+E;QACzF,OAAO,EAAE,GAAG;KACb,CAAC;SACD,MAAM,CAAC,eAAe,EAAE;QACvB,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,0CAA0C;KACrD,CAAC;IACN,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,MAAM,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAE9D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CACX,8BAA8B,GAAG,kDAAkD,CACpF,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC;QAExC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;QACjE,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC;CACF,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ExampleDiagnostic } from "./types.js";
2
+ /** Result of validating an examples directory. */
3
+ export interface ValidateDirResult {
4
+ /** All diagnostics produced (errors and warnings). */
5
+ readonly diagnostics: ExampleDiagnostic[];
6
+ /** The example files that were discovered and validated. */
7
+ readonly files: string[];
8
+ }
9
+ /**
10
+ * Discover the example files under `dir`: a top-level `examples.yaml` and/or per-interface
11
+ * files under `examples/` (`examples/<Interface>.yaml`).
12
+ */
13
+ export declare function discoverExampleFiles(dir: string): Promise<string[]>;
14
+ /**
15
+ * Validate all example files in a service directory. Discovers `examples.yaml` /
16
+ * `examples/*.yaml` and the adjacent `service.yaml` (for the `since ∈ service.yaml` check),
17
+ * then runs {@link validateExampleFiles}. Paths in diagnostics are relative to `dir`.
18
+ */
19
+ export declare function validateExamplesDir(dir: string): Promise<ValidateDirResult>;
20
+ //# sourceMappingURL=discover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/discover.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGpD,kDAAkD;AAClD,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,QAAQ,CAAC,WAAW,EAAE,iBAAiB,EAAE,CAAC;IAC1C,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;CAC1B;AAWD;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAgBzE;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqCjF"}
@@ -0,0 +1,73 @@
1
+ import { readdir, readFile, stat } from "fs/promises";
2
+ import { join, relative } from "path";
3
+ import { loadExampleFile, parseServiceVersions } from "./loader.js";
4
+ import { validateExampleFiles } from "./validate.js";
5
+ async function exists(path) {
6
+ try {
7
+ await stat(path);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ /**
15
+ * Discover the example files under `dir`: a top-level `examples.yaml` and/or per-interface
16
+ * files under `examples/` (`examples/<Interface>.yaml`).
17
+ */
18
+ export async function discoverExampleFiles(dir) {
19
+ const found = [];
20
+ const topLevel = join(dir, "examples.yaml");
21
+ if (await exists(topLevel))
22
+ found.push(topLevel);
23
+ const examplesDir = join(dir, "examples");
24
+ if ((await exists(examplesDir)) && (await stat(examplesDir)).isDirectory()) {
25
+ for (const entry of await readdir(examplesDir)) {
26
+ if (entry.endsWith(".yaml") || entry.endsWith(".yml")) {
27
+ found.push(join(examplesDir, entry));
28
+ }
29
+ }
30
+ }
31
+ return found.sort();
32
+ }
33
+ /**
34
+ * Validate all example files in a service directory. Discovers `examples.yaml` /
35
+ * `examples/*.yaml` and the adjacent `service.yaml` (for the `since ∈ service.yaml` check),
36
+ * then runs {@link validateExampleFiles}. Paths in diagnostics are relative to `dir`.
37
+ */
38
+ export async function validateExamplesDir(dir) {
39
+ const filePaths = await discoverExampleFiles(dir);
40
+ const files = [];
41
+ for (const path of filePaths) {
42
+ const content = await readFile(path, "utf-8");
43
+ files.push(loadExampleFile(relative(dir, path), content));
44
+ }
45
+ const diagnostics = [];
46
+ let serviceVersions;
47
+ const serviceYamlPath = join(dir, "service.yaml");
48
+ if (await exists(serviceYamlPath)) {
49
+ const parsed = parseServiceVersions(await readFile(serviceYamlPath, "utf-8"));
50
+ if (parsed.versions.length > 0) {
51
+ serviceVersions = parsed.versions;
52
+ }
53
+ else {
54
+ diagnostics.push({
55
+ code: "invalid-service-yaml",
56
+ message: "service.yaml has no readable 'versions' list; skipping the 'since' version-membership check.",
57
+ severity: "warning",
58
+ file: relative(dir, serviceYamlPath),
59
+ });
60
+ }
61
+ }
62
+ else if (files.length > 0) {
63
+ diagnostics.push({
64
+ code: "missing-service-yaml",
65
+ message: "No service.yaml found next to the examples; skipping the 'since' version-membership check.",
66
+ severity: "warning",
67
+ file: relative(dir, serviceYamlPath),
68
+ });
69
+ }
70
+ diagnostics.push(...validateExampleFiles(files, { serviceVersions }));
71
+ return { diagnostics, files: filePaths.map((path) => relative(dir, path)) };
72
+ }
73
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/discover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `@azure-tools/typespec-azure-examples` — tooling for the Azure unified examples format
3
+ * (`examples.yaml`). This entrypoint exposes the JSON Schema and the programmatic validation API
4
+ * used by the `tsp-examples validate` command.
5
+ */
6
+ export { discoverExampleFiles, validateExamplesDir, type ValidateDirResult } from "./discover.js";
7
+ export { isQuotedScalar, loadExampleFile, locationAt, parseServiceVersions, positionAt, type LoadedExampleFile, type Position, } from "./loader.js";
8
+ export { defaultLegacyExampleFilename, slugify, stripJsonExtension } from "./naming.js";
9
+ export { formatDiagnostics, formatSummary } from "./reporter.js";
10
+ export { checkFilePlacement, checkSemantics, type SemanticContext } from "./rules.js";
11
+ export { ExamplesYamlSchema } from "./schema.js";
12
+ export type { DiagnosticSeverity, ExampleDiagnostic, ExampleRequest, ExampleResponse, ExampleVariant, ServiceVersions, } from "./types.js";
13
+ export { checkStructure, validateExampleFiles } from "./validate.js";
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClG,OAAO,EACL,cAAc,EACd,eAAe,EACf,UAAU,EACV,oBAAoB,EACpB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,QAAQ,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,cAAc,EACd,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `@azure-tools/typespec-azure-examples` — tooling for the Azure unified examples format
3
+ * (`examples.yaml`). This entrypoint exposes the JSON Schema and the programmatic validation API
4
+ * used by the `tsp-examples validate` command.
5
+ */
6
+ export { discoverExampleFiles, validateExamplesDir } from "./discover.js";
7
+ export { isQuotedScalar, loadExampleFile, locationAt, parseServiceVersions, positionAt, } from "./loader.js";
8
+ export { defaultLegacyExampleFilename, slugify, stripJsonExtension } from "./naming.js";
9
+ export { formatDiagnostics, formatSummary } from "./reporter.js";
10
+ export { checkFilePlacement, checkSemantics } from "./rules.js";
11
+ export { ExamplesYamlSchema } from "./schema.js";
12
+ export { checkStructure, validateExampleFiles } from "./validate.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAA0B,MAAM,eAAe,CAAC;AAClG,OAAO,EACL,cAAc,EACd,eAAe,EACf,UAAU,EACV,oBAAoB,EACpB,UAAU,GAGX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAwB,MAAM,YAAY,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AASjD,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { type Document, LineCounter } from "yaml";
2
+ import type { ServiceVersions } from "./types.js";
3
+ /** A parsed `examples.yaml` (or `examples/<Interface>.yaml`) file with location metadata. */
4
+ export interface LoadedExampleFile {
5
+ /** Absolute or repo-relative path, used verbatim in diagnostics. */
6
+ readonly path: string;
7
+ /** Raw file content. */
8
+ readonly content: string;
9
+ /** The parsed YAML document (retains node ranges for precise locations). */
10
+ readonly document: Document.Parsed;
11
+ /** Plain-JS view of the document (`undefined` if the YAML could not be materialized). */
12
+ readonly data: any;
13
+ /** Line counter for translating byte offsets to line/column. */
14
+ readonly lineCounter: LineCounter;
15
+ /** Fatal YAML parse error, if any. */
16
+ readonly parseError?: string;
17
+ }
18
+ /** Parse a single examples file into a {@link LoadedExampleFile}. Never throws. */
19
+ export declare function loadExampleFile(path: string, content: string): LoadedExampleFile;
20
+ /** 1-based line/column position. */
21
+ export interface Position {
22
+ readonly line: number;
23
+ readonly col: number;
24
+ }
25
+ /** Translate a byte offset into a 1-based line/column position. */
26
+ export declare function positionAt(file: LoadedExampleFile, offset: number | undefined): Position | undefined;
27
+ /** Get the YAML node at a JSON path, or `undefined` if it doesn't exist. */
28
+ export declare function nodeAt(file: LoadedExampleFile, path: (string | number)[]): unknown;
29
+ /** Position of the node at a JSON path (start of its value). */
30
+ export declare function locationAt(file: LoadedExampleFile, path: (string | number)[]): Position | undefined;
31
+ /**
32
+ * Whether the scalar at the given path was written as a quoted string in the source.
33
+ * Returns `false` for plain (unquoted) scalars, which YAML may coerce away from a string.
34
+ */
35
+ export declare function isQuotedScalar(file: LoadedExampleFile, path: (string | number)[]): boolean;
36
+ /**
37
+ * Parse the version list from a `service.yaml` document. Tolerates a missing/empty
38
+ * `versions` list and non-string entries.
39
+ */
40
+ export declare function parseServiceVersions(content: string): ServiceVersions;
41
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAY,WAAW,EAAgC,MAAM,MAAM,CAAC;AAC1F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,6FAA6F;AAC7F,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wBAAwB;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC;IACnC,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC;IACnB,gEAAgE;IAChE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,sCAAsC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAoBhF;AAED,oCAAoC;AACpC,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CACxB,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,QAAQ,GAAG,SAAS,CAItB;AAED,4EAA4E;AAC5E,wBAAgB,MAAM,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAElF;AAED,gEAAgE;AAChE,wBAAgB,UAAU,CACxB,IAAI,EAAE,iBAAiB,EACvB,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GACxB,QAAQ,GAAG,SAAS,CAItB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAI1F;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAYrE"}
@@ -0,0 +1,70 @@
1
+ import { isScalar, LineCounter, parse, parseDocument, Scalar } from "yaml";
2
+ /** Parse a single examples file into a {@link LoadedExampleFile}. Never throws. */
3
+ export function loadExampleFile(path, content) {
4
+ const lineCounter = new LineCounter();
5
+ const document = parseDocument(content, { lineCounter });
6
+ const fatal = document.errors[0];
7
+ let data;
8
+ if (!fatal) {
9
+ try {
10
+ data = document.toJS();
11
+ }
12
+ catch {
13
+ data = undefined;
14
+ }
15
+ }
16
+ return {
17
+ path,
18
+ content,
19
+ document,
20
+ data,
21
+ lineCounter,
22
+ parseError: fatal?.message,
23
+ };
24
+ }
25
+ /** Translate a byte offset into a 1-based line/column position. */
26
+ export function positionAt(file, offset) {
27
+ if (offset === undefined)
28
+ return undefined;
29
+ const pos = file.lineCounter.linePos(offset);
30
+ return { line: pos.line, col: pos.col };
31
+ }
32
+ /** Get the YAML node at a JSON path, or `undefined` if it doesn't exist. */
33
+ export function nodeAt(file, path) {
34
+ return file.document.getIn(path, true);
35
+ }
36
+ /** Position of the node at a JSON path (start of its value). */
37
+ export function locationAt(file, path) {
38
+ const node = nodeAt(file, path);
39
+ const range = node?.range;
40
+ return positionAt(file, range?.[0]);
41
+ }
42
+ /**
43
+ * Whether the scalar at the given path was written as a quoted string in the source.
44
+ * Returns `false` for plain (unquoted) scalars, which YAML may coerce away from a string.
45
+ */
46
+ export function isQuotedScalar(file, path) {
47
+ const node = nodeAt(file, path);
48
+ if (!isScalar(node))
49
+ return false;
50
+ return node.type === Scalar.QUOTE_SINGLE || node.type === Scalar.QUOTE_DOUBLE;
51
+ }
52
+ /**
53
+ * Parse the version list from a `service.yaml` document. Tolerates a missing/empty
54
+ * `versions` list and non-string entries.
55
+ */
56
+ export function parseServiceVersions(content) {
57
+ let doc;
58
+ try {
59
+ doc = parse(content);
60
+ }
61
+ catch {
62
+ return { versions: [] };
63
+ }
64
+ const raw = Array.isArray(doc?.versions) ? doc.versions : [];
65
+ const versions = raw
66
+ .map((entry) => entry?.version)
67
+ .filter((version) => typeof version === "string");
68
+ return { versions };
69
+ }
70
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAmB1F,mFAAmF;AACnF,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe;IAC3D,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,IAAS,CAAC;IACd,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CAAC;YACH,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI;QACJ,OAAO;QACP,QAAQ;QACR,IAAI;QACJ,WAAW;QACX,UAAU,EAAE,KAAK,EAAE,OAAO;KAC3B,CAAC;AACJ,CAAC;AAQD,mEAAmE;AACnE,MAAM,UAAU,UAAU,CACxB,IAAuB,EACvB,MAA0B;IAE1B,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;AAC1C,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,MAAM,CAAC,IAAuB,EAAE,IAAyB;IACvE,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,UAAU,CACxB,IAAuB,EACvB,IAAyB;IAEzB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChC,MAAM,KAAK,GAAI,IAAyD,EAAE,KAAK,CAAC;IAChF,OAAO,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAuB,EAAE,IAAyB;IAC/E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAClC,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,YAAY,CAAC;AAChF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC1B,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,MAAM,QAAQ,GAAG,GAAG;SACjB,GAAG,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC;SACnC,MAAM,CAAC,CAAC,OAAgB,EAAqB,EAAE,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC;IAChF,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Shared naming convention for legacy `x-ms-examples` files, used both by `tsp-examples-migrate`
3
+ * (to decide when the original name/key can be reconstructed and therefore omitted from
4
+ * `examples.yaml`) and by the `typespec-autorest` emitter (to materialize the legacy files). Keeping
5
+ * this in one place guarantees the two sides agree, so the round-trip stays lossless.
6
+ */
7
+ /** Turn an arbitrary title into a file-name-safe slug (`With WebHook` -> `With_WebHook`). */
8
+ export declare function slugify(value: string): string;
9
+ /** Strip a trailing `.json` extension (case-insensitive). */
10
+ export declare function stripJsonExtension(fileName: string): string;
11
+ /**
12
+ * The conventional legacy example file name for an operation. The dominant Azure convention names
13
+ * example files after the `operationId` (`Widgets_Get.json`); when an operation carries multiple
14
+ * distinct examples the title is appended (`Widgets_Get_WithFilter.json`).
15
+ */
16
+ export declare function defaultLegacyExampleFilename(operationId: string, title?: string): string;
17
+ //# sourceMappingURL=naming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../src/naming.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,6FAA6F;AAC7F,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK7C;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAExF"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Shared naming convention for legacy `x-ms-examples` files, used both by `tsp-examples-migrate`
3
+ * (to decide when the original name/key can be reconstructed and therefore omitted from
4
+ * `examples.yaml`) and by the `typespec-autorest` emitter (to materialize the legacy files). Keeping
5
+ * this in one place guarantees the two sides agree, so the round-trip stays lossless.
6
+ */
7
+ /** Turn an arbitrary title into a file-name-safe slug (`With WebHook` -> `With_WebHook`). */
8
+ export function slugify(value) {
9
+ return value
10
+ .replace(/[^A-Za-z0-9]+/g, "_")
11
+ .replace(/^_|_$/g, "")
12
+ .slice(0, 120);
13
+ }
14
+ /** Strip a trailing `.json` extension (case-insensitive). */
15
+ export function stripJsonExtension(fileName) {
16
+ return fileName.replace(/\.json$/i, "");
17
+ }
18
+ /**
19
+ * The conventional legacy example file name for an operation. The dominant Azure convention names
20
+ * example files after the `operationId` (`Widgets_Get.json`); when an operation carries multiple
21
+ * distinct examples the title is appended (`Widgets_Get_WithFilter.json`).
22
+ */
23
+ export function defaultLegacyExampleFilename(operationId, title) {
24
+ return title ? `${operationId}_${slugify(title)}.json` : `${operationId}.json`;
25
+ }
26
+ //# sourceMappingURL=naming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"naming.js","sourceRoot":"","sources":["../../src/naming.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,6FAA6F;AAC7F,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,KAAK;SACT,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACnB,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAAC,WAAmB,EAAE,KAAc;IAC9E,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,WAAW,OAAO,CAAC;AACjF,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ExampleDiagnostic } from "./types.js";
2
+ /** Format a set of diagnostics for terminal output, grouped by file. */
3
+ export declare function formatDiagnostics(diagnostics: readonly ExampleDiagnostic[], baseDir?: string): string;
4
+ /** Format a one-line summary of the diagnostics. */
5
+ export declare function formatSummary(diagnostics: readonly ExampleDiagnostic[]): string;
6
+ //# sourceMappingURL=reporter.d.ts.map