@contractkit/plugin-bruno 1.3.0 → 1.4.1
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/.turbo/turbo-build$colon$ci.log +6 -6
- package/.turbo/turbo-test$colon$ci.log +15 -15
- package/CHANGELOG.md +19 -0
- package/coverage/clover.xml +369 -333
- package/coverage/coverage-final.json +3 -3
- package/coverage/index.html +21 -21
- package/coverage/src/codegen-bruno.ts.html +760 -181
- package/coverage/src/index.html +30 -30
- package/coverage/src/index.ts.html +103 -76
- package/coverage/tests/helpers.ts.html +16 -16
- package/coverage/tests/index.html +1 -1
- package/dist/codegen-bruno.d.ts +41 -3
- package/dist/codegen-bruno.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +185 -85
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/codegen-bruno.ts +236 -43
- package/src/index.ts +60 -51
- package/tests/codegen-bruno.test.ts +114 -7
package/dist/codegen-bruno.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { OpRootNode, ContractRootNode } from '@contractkit/core';
|
|
1
|
+
import type { OpRootNode, ContractRootNode, IncrementalManifest, IncrementalResult as IncrementalResultBase } from '@contractkit/core';
|
|
2
2
|
/** A single file produced by the Bruno codegen — a relative output path and its YAML content. */
|
|
3
3
|
export interface OpenCollectionFile {
|
|
4
4
|
relativePath: string;
|
|
@@ -6,6 +6,12 @@ export interface OpenCollectionFile {
|
|
|
6
6
|
}
|
|
7
7
|
/** Manifest filename — tracks which files this plugin previously generated so subsequent runs can clean up only those, leaving any user-added files alone. */
|
|
8
8
|
export declare const MANIFEST_FILENAME = ".contractkit-bruno-manifest.json";
|
|
9
|
+
/**
|
|
10
|
+
* Bumped whenever the codegen output shape changes in a way that should bust
|
|
11
|
+
* every per-op fingerprint. Mixed into the per-op fingerprint so a plugin
|
|
12
|
+
* upgrade forces full regeneration even when source `.ck` files are unchanged.
|
|
13
|
+
*/
|
|
14
|
+
export declare const BRUNO_CODEGEN_VERSION = "1";
|
|
9
15
|
/** Subset of a security scheme sufficient for Bruno auth generation (non-HMAC). */
|
|
10
16
|
export interface BrunoSecurityScheme {
|
|
11
17
|
type: string;
|
|
@@ -49,14 +55,46 @@ export interface OpenCollectionOptions {
|
|
|
49
55
|
*/
|
|
50
56
|
environments?: Record<string, Record<string, unknown>>;
|
|
51
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* @deprecated Use {@link IncrementalManifest} from `@contractkit/core`. Re-exported here for backwards compatibility.
|
|
60
|
+
*/
|
|
61
|
+
export type BrunoManifest = IncrementalManifest;
|
|
62
|
+
/** Result of {@link generateOpenCollectionIncremental}. Renamed `skippedOpCount` for Bruno-specific clarity but otherwise the shared {@link IncrementalResultBase}. */
|
|
63
|
+
export interface IncrementalResult extends Omit<IncrementalResultBase, 'skippedUnitCount'> {
|
|
64
|
+
/** Number of ops whose codegen was skipped because their fingerprint matched. */
|
|
65
|
+
skippedOpCount: number;
|
|
66
|
+
}
|
|
52
67
|
/**
|
|
53
68
|
* Generates an OpenCollection (https://spec.opencollection.com/) API collection
|
|
54
69
|
* from a set of operation roots. Produces opencollection.yml, an environment
|
|
55
70
|
* file, and one .yml request file per operation.
|
|
71
|
+
*
|
|
72
|
+
* This is the full-regeneration entry point — every file is rebuilt from scratch.
|
|
73
|
+
* For cache-aware incremental builds, use {@link generateOpenCollectionIncremental}.
|
|
56
74
|
*/
|
|
57
75
|
export declare function generateOpenCollection(roots: OpRootNode[], options: OpenCollectionOptions): OpenCollectionFile[];
|
|
58
|
-
/**
|
|
59
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Cache-aware variant of {@link generateOpenCollection}. Skips re-rendering YAML
|
|
78
|
+
* for any op whose fingerprint matches the entry in `prevManifest`. The caller is
|
|
79
|
+
* responsible for emitting `filesToWrite`, deleting `deletedPaths`, and persisting
|
|
80
|
+
* `manifest` so the next run can match against it.
|
|
81
|
+
*
|
|
82
|
+
* Global files (collection root, env files, folder.yml) are always regenerated —
|
|
83
|
+
* they're cheap and depend on options the manifest doesn't fingerprint.
|
|
84
|
+
*/
|
|
85
|
+
export declare function generateOpenCollectionIncremental(roots: OpRootNode[], options: OpenCollectionOptions, prevManifest: IncrementalManifest, fileExists?: (relativePath: string) => boolean): IncrementalResult;
|
|
86
|
+
/** Empty-state manifest, used when none has been written yet (or when the cache is being bypassed). */
|
|
87
|
+
export declare function emptyManifest(): IncrementalManifest;
|
|
88
|
+
/**
|
|
89
|
+
* Parse a previously-written manifest. Accepts both v1 (`{ files: string[] }`) and v2
|
|
90
|
+
* (full {@link IncrementalManifest}) shapes. v1 manifests are returned with an empty
|
|
91
|
+
* `units` map so the next run treats every op as a cache miss while still cleaning up
|
|
92
|
+
* the tracked file list.
|
|
93
|
+
*
|
|
94
|
+
* Returns an empty manifest on any parse error so a stale/garbled file never blocks
|
|
95
|
+
* regeneration.
|
|
96
|
+
*/
|
|
97
|
+
export declare function parseManifest(content: string): IncrementalManifest;
|
|
60
98
|
/**
|
|
61
99
|
* Deep-merges a YAML override string into a generated YAML string.
|
|
62
100
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen-bruno.d.ts","sourceRoot":"","sources":["../src/codegen-bruno.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,UAAU,EAMV,gBAAgB,
|
|
1
|
+
{"version":3,"file":"codegen-bruno.d.ts","sourceRoot":"","sources":["../src/codegen-bruno.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,UAAU,EAMV,gBAAgB,EAGhB,mBAAmB,EAEnB,iBAAiB,IAAI,qBAAqB,EAC7C,MAAM,mBAAmB,CAAC;AAe3B,iGAAiG;AACjG,MAAM,WAAW,kBAAkB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,8JAA8J;AAC9J,eAAO,MAAM,iBAAiB,qCAAqC,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,mFAAmF;AACnF,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;CACf;AAED,kHAAkH;AAClH,MAAM,WAAW,gBAAgB;IAC7B,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CACjD;AAED,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACnC,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC1D;AAiBD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAEhD,uKAAuK;AACvK,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,qBAAqB,EAAE,kBAAkB,CAAC;IACtF,iFAAiF;IACjF,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,qBAAqB,GAAG,kBAAkB,EAAE,CAGhH;AAED;;;;;;;;GAQG;AACH,wBAAgB,iCAAiC,CAC7C,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,EAAE,qBAAqB,EAC9B,YAAY,EAAE,mBAAmB,EACjC,UAAU,GAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAoB,GAC3D,iBAAiB,CAiEnB;AAkHD,uGAAuG;AACvG,wBAAgB,aAAa,IAAI,mBAAmB,CAEnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAmBlE;AAsBD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAOxF;AA2cD,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMhD;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASjD"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAiB,WAAW,EAAqD,MAAM,mBAAmB,CAAC;AAE1I,8GAA8G;AAC9G,MAAM,WAAW,iBAAiB;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC1D;AAED,mHAAmH;AACnH,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IACzD,IAAI,CAAC,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;KAAE,CAAC;CACnF;AAID;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAavF;AAQD,QAAA,MAAM,MAAM,EAAE,iBAOb,CAAC;AAEF,eAAe,MAAM,CAAC;AAItB;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC7B,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;CAAE,GAChF,iBAAiB,CAUnB"}
|
package/dist/index.js
CHANGED
|
@@ -6,23 +6,24 @@ import { resolve, basename as basename2, dirname } from "path";
|
|
|
6
6
|
import { existsSync, readFileSync, rmSync, readdirSync, rmdirSync } from "fs";
|
|
7
7
|
|
|
8
8
|
// src/codegen-bruno.ts
|
|
9
|
-
import { resolveSecurity, resolveModifiers, SECURITY_NONE } from "@contractkit/core";
|
|
9
|
+
import { resolveSecurity, resolveModifiers, SECURITY_NONE, collectTransitiveModelRefs, runIncrementalCodegen, parseIncrementalManifest, emptyIncrementalManifest, hashFingerprint, INCREMENTAL_MANIFEST_VERSION } from "@contractkit/core";
|
|
10
10
|
import { basename } from "path";
|
|
11
11
|
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
12
12
|
var MANIFEST_FILENAME = ".contractkit-bruno-manifest.json";
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
var BRUNO_CODEGEN_VERSION = "1";
|
|
14
|
+
function generateOpenCollectionIncremental(roots, options, prevManifest, fileExists = () => true) {
|
|
15
15
|
const modelMap = buildModelMap(options.contractRoots ?? []);
|
|
16
16
|
const authOpts = options.auth;
|
|
17
17
|
const defaultScheme = authOpts?.defaultScheme ? authOpts.schemes?.[authOpts.defaultScheme] : void 0;
|
|
18
18
|
const randomExamples = options.randomExamples ?? false;
|
|
19
19
|
const includeInternal = options.includeInternal ?? true;
|
|
20
|
-
|
|
20
|
+
const globalFiles = [];
|
|
21
|
+
globalFiles.push({
|
|
21
22
|
relativePath: "opencollection.yml",
|
|
22
23
|
content: generateCollectionRoot(options.collectionName, defaultScheme)
|
|
23
24
|
});
|
|
24
25
|
for (const envFile of generateEnvFiles(options.environments, defaultScheme)) {
|
|
25
|
-
|
|
26
|
+
globalFiles.push(envFile);
|
|
26
27
|
}
|
|
27
28
|
const sortedRoots = [
|
|
28
29
|
...roots
|
|
@@ -33,11 +34,12 @@ function generateOpenCollection(roots, options) {
|
|
|
33
34
|
if (cmp !== 0) return cmp;
|
|
34
35
|
return (a.meta["subarea"] ?? "").localeCompare(b.meta["subarea"] ?? "");
|
|
35
36
|
});
|
|
37
|
+
const units = [];
|
|
36
38
|
for (let rootIdx = 0; rootIdx < sortedRoots.length; rootIdx++) {
|
|
37
39
|
const root = sortedRoots[rootIdx];
|
|
38
40
|
const folder = root.meta["area"] ? slugifyName(root.meta["area"]) : deriveFolderName(root.file);
|
|
39
41
|
const displayName = (root.meta["area"] ?? folder).charAt(0).toUpperCase() + (root.meta["area"] ?? folder).slice(1);
|
|
40
|
-
|
|
42
|
+
globalFiles.push({
|
|
41
43
|
relativePath: `${folder}/folder.yml`,
|
|
42
44
|
content: generateFolderFile(displayName, rootIdx + 1)
|
|
43
45
|
});
|
|
@@ -46,61 +48,164 @@ function generateOpenCollection(roots, options) {
|
|
|
46
48
|
const requestDir = subareaSlug ? `${folder}/${subareaSlug}` : folder;
|
|
47
49
|
if (subareaSlug) {
|
|
48
50
|
const subareaDisplayName = subarea.charAt(0).toUpperCase() + subarea.slice(1);
|
|
49
|
-
|
|
51
|
+
globalFiles.push({
|
|
50
52
|
relativePath: `${requestDir}/folder.yml`,
|
|
51
53
|
content: generateFolderFile(subareaDisplayName, 1)
|
|
52
54
|
});
|
|
53
55
|
}
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
});
|
|
63
|
-
}
|
|
56
|
+
for (const entry of buildOpEntries(root, requestDir, includeInternal)) {
|
|
57
|
+
units.push({
|
|
58
|
+
key: entry.opKey,
|
|
59
|
+
fingerprint: computeOpFingerprint(entry, modelMap, defaultScheme, randomExamples),
|
|
60
|
+
render: /* @__PURE__ */ __name(() => [
|
|
61
|
+
renderOpFile(entry, modelMap, defaultScheme, randomExamples)
|
|
62
|
+
], "render")
|
|
63
|
+
});
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
65
|
+
}
|
|
66
|
+
const result = runIncrementalCodegen({
|
|
67
|
+
codegenVersion: BRUNO_CODEGEN_VERSION,
|
|
68
|
+
manifestFilename: MANIFEST_FILENAME,
|
|
69
|
+
prevManifest,
|
|
70
|
+
globalFiles,
|
|
71
|
+
units,
|
|
72
|
+
fileExists
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
filesToWrite: result.filesToWrite,
|
|
76
|
+
manifest: result.manifest,
|
|
77
|
+
deletedPaths: result.deletedPaths,
|
|
78
|
+
skippedOpCount: result.skippedUnitCount
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
__name(generateOpenCollectionIncremental, "generateOpenCollectionIncremental");
|
|
82
|
+
function buildOpEntries(root, requestDir, includeInternal) {
|
|
83
|
+
const requests = [];
|
|
84
|
+
for (const route of root.routes) {
|
|
85
|
+
for (const op of route.operations) {
|
|
86
|
+
if (!includeInternal && resolveModifiers(route, op).includes("internal")) continue;
|
|
87
|
+
requests.push({
|
|
88
|
+
route,
|
|
89
|
+
op,
|
|
90
|
+
requestName: op.name ?? route.path
|
|
78
91
|
});
|
|
79
|
-
seq++;
|
|
80
92
|
}
|
|
81
93
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
94
|
+
requests.sort((a, b) => a.requestName.localeCompare(b.requestName));
|
|
95
|
+
const entries = [];
|
|
96
|
+
let seq = 1;
|
|
97
|
+
for (const { route, op, requestName } of requests) {
|
|
98
|
+
const fileName = op.name ? `${slugifyName(op.name)}.yml` : `${op.method}-${sanitizePath(route.path)}.yml`;
|
|
99
|
+
entries.push({
|
|
100
|
+
opKey: `${root.file}::${op.method.toUpperCase()} ${route.path}`,
|
|
101
|
+
relativePath: `${requestDir}/${fileName}`,
|
|
102
|
+
requestName,
|
|
103
|
+
seq,
|
|
104
|
+
route,
|
|
105
|
+
op,
|
|
106
|
+
root
|
|
107
|
+
});
|
|
108
|
+
seq++;
|
|
109
|
+
}
|
|
110
|
+
return entries;
|
|
111
|
+
}
|
|
112
|
+
__name(buildOpEntries, "buildOpEntries");
|
|
113
|
+
function renderOpFile(entry, modelMap, defaultScheme, randomExamples) {
|
|
114
|
+
let content = generateRequestFile(entry.route, entry.op, entry.requestName, entry.seq, modelMap, entry.root, defaultScheme, randomExamples);
|
|
115
|
+
const brunoExt = entry.op.pluginExtensions?.["bruno"];
|
|
116
|
+
const pluginOverride = brunoExt && typeof brunoExt === "object" && !Array.isArray(brunoExt) ? brunoExt["template"] : void 0;
|
|
117
|
+
if (typeof pluginOverride === "string") {
|
|
118
|
+
content = mergePluginFile(content, pluginOverride);
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
relativePath: entry.relativePath,
|
|
122
|
+
content
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
__name(renderOpFile, "renderOpFile");
|
|
126
|
+
function computeOpFingerprint(entry, modelMap, defaultScheme, randomExamples) {
|
|
127
|
+
const referencedModels = collectTransitiveModelRefs(collectOpTypeNodes(entry.route, entry.op), modelMap);
|
|
128
|
+
const modelSnapshot = {};
|
|
129
|
+
for (const name of [
|
|
130
|
+
...referencedModels
|
|
131
|
+
].sort()) {
|
|
132
|
+
const m = modelMap.get(name);
|
|
133
|
+
if (m) modelSnapshot[name] = m;
|
|
134
|
+
}
|
|
135
|
+
const routeShape = {
|
|
136
|
+
path: entry.route.path,
|
|
137
|
+
params: entry.route.params ?? null,
|
|
138
|
+
modifiers: entry.route.modifiers ?? null,
|
|
139
|
+
security: entry.route.security ?? null,
|
|
140
|
+
description: entry.route.description ?? null
|
|
141
|
+
};
|
|
142
|
+
return hashFingerprint({
|
|
143
|
+
v: BRUNO_CODEGEN_VERSION,
|
|
144
|
+
opKey: entry.opKey,
|
|
145
|
+
relativePath: entry.relativePath,
|
|
146
|
+
requestName: entry.requestName,
|
|
147
|
+
seq: entry.seq,
|
|
148
|
+
route: routeShape,
|
|
149
|
+
op: entry.op,
|
|
150
|
+
rootMeta: entry.root.meta,
|
|
151
|
+
rootFile: entry.root.file,
|
|
152
|
+
defaultScheme: defaultScheme ?? null,
|
|
153
|
+
randomExamples,
|
|
154
|
+
models: modelSnapshot
|
|
91
155
|
});
|
|
92
|
-
return files;
|
|
93
156
|
}
|
|
94
|
-
__name(
|
|
157
|
+
__name(computeOpFingerprint, "computeOpFingerprint");
|
|
158
|
+
function collectOpTypeNodes(route, op) {
|
|
159
|
+
const out = [];
|
|
160
|
+
pushFromParamSource(route.params, out);
|
|
161
|
+
pushFromParamSource(op.query, out);
|
|
162
|
+
pushFromParamSource(op.headers, out);
|
|
163
|
+
if (op.request) {
|
|
164
|
+
for (const body of op.request.bodies) out.push(body.bodyType);
|
|
165
|
+
}
|
|
166
|
+
for (const resp of op.responses) {
|
|
167
|
+
if (resp.bodyType) out.push(resp.bodyType);
|
|
168
|
+
if (resp.headers) {
|
|
169
|
+
for (const h of resp.headers) out.push(h.type);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
__name(collectOpTypeNodes, "collectOpTypeNodes");
|
|
175
|
+
function pushFromParamSource(src, out) {
|
|
176
|
+
if (!src) return;
|
|
177
|
+
if (src.kind === "params") {
|
|
178
|
+
for (const n of src.nodes) out.push(n.type);
|
|
179
|
+
} else if (src.kind === "ref") {
|
|
180
|
+
out.push({
|
|
181
|
+
kind: "ref",
|
|
182
|
+
name: src.name
|
|
183
|
+
});
|
|
184
|
+
} else if (src.kind === "type") {
|
|
185
|
+
out.push(src.node);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
__name(pushFromParamSource, "pushFromParamSource");
|
|
189
|
+
function emptyManifest() {
|
|
190
|
+
return emptyIncrementalManifest(BRUNO_CODEGEN_VERSION);
|
|
191
|
+
}
|
|
192
|
+
__name(emptyManifest, "emptyManifest");
|
|
95
193
|
function parseManifest(content) {
|
|
194
|
+
const parsed = parseIncrementalManifest(content);
|
|
195
|
+
if (parsed.files.length > 0 || Object.keys(parsed.units).length > 0) return parsed;
|
|
96
196
|
try {
|
|
97
|
-
const
|
|
98
|
-
if (Array.isArray(
|
|
99
|
-
return
|
|
197
|
+
const raw = JSON.parse(content);
|
|
198
|
+
if (Array.isArray(raw?.files) && raw.files.every((f) => typeof f === "string")) {
|
|
199
|
+
return {
|
|
200
|
+
version: INCREMENTAL_MANIFEST_VERSION,
|
|
201
|
+
codegenVersion: "",
|
|
202
|
+
files: raw.files,
|
|
203
|
+
units: {}
|
|
204
|
+
};
|
|
100
205
|
}
|
|
101
206
|
} catch {
|
|
102
207
|
}
|
|
103
|
-
return
|
|
208
|
+
return emptyManifest();
|
|
104
209
|
}
|
|
105
210
|
__name(parseManifest, "parseManifest");
|
|
106
211
|
function deepMerge(base, override) {
|
|
@@ -640,64 +745,59 @@ function describe(value) {
|
|
|
640
745
|
__name(describe, "describe");
|
|
641
746
|
var plugin = {
|
|
642
747
|
name: "bruno",
|
|
643
|
-
cacheKey: "bruno",
|
|
644
748
|
validateExtension: validateBrunoExtension,
|
|
645
749
|
async generateTargets({ opRoots, contractRoots }, ctx) {
|
|
646
750
|
const { auth, ...config } = ctx.options;
|
|
647
|
-
|
|
648
|
-
const outDir = resolve(base, config.output ?? "bruno-collection");
|
|
649
|
-
const collectionName = config.collectionName ?? basename2(ctx.rootDir);
|
|
650
|
-
cleanupTrackedFiles(outDir);
|
|
651
|
-
const files = generateOpenCollection(opRoots, {
|
|
652
|
-
collectionName,
|
|
653
|
-
contractRoots,
|
|
654
|
-
auth,
|
|
655
|
-
randomExamples: config.randomExamples ?? true,
|
|
656
|
-
includeInternal: config.includeInternal,
|
|
657
|
-
environments: config.environments
|
|
658
|
-
});
|
|
659
|
-
for (const { relativePath, content } of files) {
|
|
660
|
-
ctx.emitFile(resolve(outDir, relativePath), content);
|
|
661
|
-
}
|
|
751
|
+
await runBrunoCodegen(opRoots, contractRoots, ctx, config, auth);
|
|
662
752
|
}
|
|
663
753
|
};
|
|
664
754
|
var index_default = plugin;
|
|
665
755
|
function createBrunoPlugin(config, rootDir, auth) {
|
|
666
756
|
return {
|
|
667
757
|
name: "bruno",
|
|
668
|
-
cacheKey: `bruno:${JSON.stringify(config)}`,
|
|
669
758
|
validateExtension: validateBrunoExtension,
|
|
670
759
|
async generateTargets({ opRoots, contractRoots }, ctx) {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
const files = generateOpenCollection(opRoots, {
|
|
676
|
-
collectionName,
|
|
677
|
-
contractRoots,
|
|
678
|
-
auth,
|
|
679
|
-
randomExamples: config.randomExamples ?? true,
|
|
680
|
-
includeInternal: config.includeInternal,
|
|
681
|
-
environments: config.environments
|
|
682
|
-
});
|
|
683
|
-
for (const { relativePath, content } of files) {
|
|
684
|
-
ctx.emitFile(resolve(outDir, relativePath), content);
|
|
685
|
-
}
|
|
760
|
+
await runBrunoCodegen(opRoots, contractRoots, {
|
|
761
|
+
...ctx,
|
|
762
|
+
rootDir
|
|
763
|
+
}, config, auth);
|
|
686
764
|
}
|
|
687
765
|
};
|
|
688
766
|
}
|
|
689
767
|
__name(createBrunoPlugin, "createBrunoPlugin");
|
|
690
|
-
function
|
|
768
|
+
async function runBrunoCodegen(opRoots, contractRoots, ctx, config, auth) {
|
|
769
|
+
const base = config.baseDir ? resolve(ctx.rootDir, config.baseDir) : ctx.rootDir;
|
|
770
|
+
const outDir = resolve(base, config.output ?? "bruno-collection");
|
|
771
|
+
const collectionName = config.collectionName ?? basename2(ctx.rootDir);
|
|
772
|
+
const prevManifest = ctx.cacheEnabled ? readManifest(outDir) : emptyManifest();
|
|
773
|
+
const result = generateOpenCollectionIncremental(opRoots, {
|
|
774
|
+
collectionName,
|
|
775
|
+
contractRoots,
|
|
776
|
+
auth,
|
|
777
|
+
randomExamples: config.randomExamples ?? true,
|
|
778
|
+
includeInternal: config.includeInternal,
|
|
779
|
+
environments: config.environments
|
|
780
|
+
}, prevManifest, (relPath) => existsSync(resolve(outDir, relPath)));
|
|
781
|
+
deleteStalePaths(outDir, result.deletedPaths);
|
|
782
|
+
for (const { relativePath, content } of result.filesToWrite) {
|
|
783
|
+
ctx.emitFile(resolve(outDir, relativePath), content);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
__name(runBrunoCodegen, "runBrunoCodegen");
|
|
787
|
+
function readManifest(outDir) {
|
|
691
788
|
const manifestPath = resolve(outDir, MANIFEST_FILENAME);
|
|
692
|
-
if (!existsSync(manifestPath)) return;
|
|
693
|
-
let tracked;
|
|
789
|
+
if (!existsSync(manifestPath)) return emptyManifest();
|
|
694
790
|
try {
|
|
695
|
-
|
|
791
|
+
return parseManifest(readFileSync(manifestPath, "utf-8"));
|
|
696
792
|
} catch {
|
|
697
|
-
return;
|
|
793
|
+
return emptyManifest();
|
|
698
794
|
}
|
|
795
|
+
}
|
|
796
|
+
__name(readManifest, "readManifest");
|
|
797
|
+
function deleteStalePaths(outDir, relPaths) {
|
|
798
|
+
if (relPaths.length === 0) return;
|
|
699
799
|
const removedDirs = /* @__PURE__ */ new Set();
|
|
700
|
-
for (const rel of
|
|
800
|
+
for (const rel of relPaths) {
|
|
701
801
|
const abs = resolve(outDir, rel);
|
|
702
802
|
if (existsSync(abs)) {
|
|
703
803
|
rmSync(abs, {
|
|
@@ -722,7 +822,7 @@ function cleanupTrackedFiles(outDir) {
|
|
|
722
822
|
}
|
|
723
823
|
}
|
|
724
824
|
}
|
|
725
|
-
__name(
|
|
825
|
+
__name(deleteStalePaths, "deleteStalePaths");
|
|
726
826
|
export {
|
|
727
827
|
createBrunoPlugin,
|
|
728
828
|
index_default as default,
|